Pithy summary for codata (Where a comonad is a 'type for input impurity') - monads

In terms of pithy summaries - this description of Comonads seems to win - describing them as a 'type for input impurity'.
What is an equivalent pithy (one-sentence) description for codata?

"Codata are types inhabited by values that may be infinite"
This contrasts with "data" which is inhabited only by finite values. For example, if we take the "data" definition of lists, it is inhabited by lists of finite length (as in ML), but if we take the "codata" definition it is inhabited also by infinite length lists (as in Haskell, e.g. x = 1 : x).
Comonads and codata are not necessarily related (although perhaps some might think so due to Kieburtz' paper Comonads and codata in Haskell).

Related

Why isn't an order type used for comparisons in OCaml?

I have yet to find a suitable answer for an OCaml design decision, and hope one of those here with in-depth knowledge of OCaml's implementation can shed some light.
In SML, if we evaluate Int.compare(6, 9) we get LESS which is a constructor for the order type (the others being GREATER and EQUAL). In OCaml, if we evaluate compare 6 9 we get -1.
Was there a specific reason to favor having comparison functions return zero, a negative number, or a positive number in OCaml's standard library, rather than an algebraic data type as in SML?

Haskell - Tuples and Lists as built-in types: how are they actually declared?

In chapter 2 of "A gentle introduction to Haskell", user-defined types are explained and then the notion that built-in types are, apart from a special syntax, no more different than user-defined ones:
Earlier we introduced several "built-in" types such as lists, tuples, integers, and characters. We have also shown how new user-defined types can be defined. Aside from special syntax, are the built-in types in any way more special than the user-defined ones? The answer is no. (The special syntax is for convenience and for consistency with historical convention, but has no semantic consequences.)
So you could define a tuple like to the following:
data (a,b) = (a,b)
data (a,b,c) = (a,b,c)
data (a,b,c,d) = (a,b,c,d)
Which sure you cannot because that would require an infinite number of declarations. So how are these types actually implemented? Especially regarding the fact that only against a type declaration you can pattern-match?
Since GHC is open source, we can just look at it:
The tuples are a lot less magical than you think:
From https://github.com/ghc/ghc/blob/master/libraries/ghc-prim/GHC/Tuple.hs
data (a,b) = (a,b)
data (a,b,c) = (a,b,c)
data (a,b,c,d) = (a,b,c,d)
data (a,b,c,d,e) = (a,b,c,d,e)
data (a,b,c,d,e,f) = (a,b,c,d,e,f)
data (a,b,c,d,e,f,g) = (a,b,c,d,e,f,g)
-- and so on...
So, tuples with different arities are just different data types, and tuples with very big number of arities is not supported.
Lists are also around there:
From https://github.com/ghc/ghc/blob/master/libraries/ghc-prim/GHC/Types.hs#L101
data [] a = [] | a : [a]
But there is a little bit of magic (special syntax) for lists.
Note: I know that GitHub is not where GHC is developed, but searching "ghc source code" on Google did not yield the correct page, and GitHub was the easiest.
You defined three tuple types there, not one hence your argument with the infinite number of declarations doesn't cut. A standard confoming Haskell needs to support only a finite number of tuple types. Hence finitely many declarations.
In fact, you can define:
data Pair a b = Pair a b
and this is isomorphic to an ordinary 2-tuple.

Why would I ever want to use Maybe instead of a List?

Seeing as the Maybe type is isomorphic to the set of null and singleton lists, why would anyone ever want to use the Maybe type when I could just use lists to accomodate absence?
Because if you match a list against the patterns [] and [x] that's not an exhaustive match and you'll get a warning about that, forcing you to either add another case that'll never get called or to ignore the warning.
Matching a Maybe against Nothing and Just x however is exhaustive. So you'll only get a warning if you fail to match one of those cases.
If you choose your types such that they can only represent values that you may actually produce, you can rely on non-exhaustiveness warnings to tell you about bugs in your code where you forget to check for a given a case. If you choose more "permissive" types, you'll always have to think about whether a warning represents an actual bug or just an impossible case.
You should strive to have accurate types. Maybe expresses that there is exactly one value or that there is none. Many imperative languages represent the "none" case by the value null.
If you chose a list instead of Maybe, all your functions would be faced with the possibility that they get a list with more than one member. Probably many of them would only be defined for one value, and would have to fail on a pattern match. By using Maybe, you avoid a class of runtime errors entirely.
Building on existing (and correct) answers, I'll mention a typeclass based answer.
Different types convey different intentions - returning a Maybe a represents a computation with the possiblity of failing while [a] could represent non-determinism (or, in simpler terms, multiple possible return values).
This plays into the fact that different types have different instances for typeclasses - and these instances cater to the underlying essence the type conveys. Take Alternative and its operator (<|>) which represents what it means to combine (or choose) between arguments given.
Maybe a Combining computations that can fail just means taking the first that is not Nothing
[a] Combining two computations that each had multiple return values just means concatenating together all possible values.
Then, depending on which types your functions use, (<|>) would behave differently. Of course, you could argue that you don't need (<|>) or anything like that, but then you are missing out on one of Haskell's main strengths: it's many high-level combinator libraries.
As a general rule, we like our types to be as snug fitting and intuitive as possible. That way, we are not fighting the standard libraries and our code is more readable.
Lisp, Scheme, Python, Ruby, JavaScript, etc., manage to get along with just one type each, which you could represent in Haskell with a big sum type. Every function handling a JavaScript (or whatever) value must be prepared to receive a number, a string, a function, a piece of the document object model, etc., and throw an exception if it gets something unexpected. People who program in typed languages like Haskell prefer to limit the number of unexpected things that can occur. They also like to express ideas using types, making types useful (and machine-checked) documentation. The closer the types come to representing the intended meaning, the more useful they are.
Because there are an infinite number of possible lists, and a finite number of possible values for the Maybe type. It perfectly represents one thing or the absence of something without any other possibility.
Several answers have mentioned exhaustiveness as a factor here. I think it is a factor, but not the biggest one, because there is a way to consistently treat lists as if they were Maybes, which the listToMaybe function illustrates:
listToMaybe :: [a] -> Maybe a
listToMaybe [] = Nothing
listToMaybe (a:_) = Just a
That's an exhaustive pattern match, which rules out any straightforward errors.
The factor I'd highlight as bigger is that by using the type that more precisely models the behavior of your code, you eliminate potential behaviors that would be possible if you used a more general alternative. Say for example you have some context in your code where you uses a type of the form a -> [b], though the only correct alternatives (given your program's specification) are empty or singleton lists. Try as hard as you may to enforce the convention that this context should obey that rule, it's still possible that you'll mess up and:
Somehow a function used in that context will produce a list of two or more items;
And somehow a function that uses the results produced in that context will observe whether the lists have two or more items, and behave incorrectly in that case.
Example: some code that expects there to be no more than one value will blindly print the contents of the list and thus print multiple items when only one was supposed to be.
But if you use Maybe, then there really must be either one value or none, and the compiler enforces this.
Even though isomorphic, e.g. QuickCheck will run slower because of the increase in search space.

Monad: Why does Identity matter, what's going to happen if there's no such special member in a set?

I'm trying to learn the concept of monad, I'm watching this excellent video Brian Beckend trying to explain what is monad.
When he talks about monoid, it's a collection of types, it has a rule of composition, and this composition has to obey 2 rules:
associative: x # (y # z ) = (x # y) # z
a special member in the collection: x # id = x and id # x = x
I'm using # symbol representing composition. id means the special member.
The second point is what I'm trying to understand. why does this matter ? what if there's no such special member ?
When I learn new concept, I always try to relate these abstract concept to some other concrete things, so that I can fully understand and learn them by heart.
So what I'm trying to relate monad and monoid to is lego. So all the building blocks in a lego set forms a collection. and the composition rule is composite them into new shape of building blocks. and it's obvious the composition obey the first rule: associative. But there's no special building block which can composite with other building block and get the same back. So it fails to obey the second rule.
But lego is still highly composable. What has been missing or lack when lego fails to obey the second rule ? What is the consequence ?
Or put it this way, comparing to other monoid which obey all those rules. What feature does other monoid has but lego doesn't ?
A monoid without an identity element is called a semigroup and its still a fine and useful construct. It just gives us something different. Consider, for example, a fold on a list. We can do this by mapping every element of a list to a monoid and then composing them all. But if you only have a semigroup, you can't fold on a possibly empty list.
Consider another example -- the integers greater than zero, versus the integers greater than or equal to zero. In the latter case we have a monoid, since zero is literally our zero element. So I can solve for example, the equation "5 + x = 5". In the former case, with a semigroup, I can't solve that equation. Or I can say "you have no apples, I then give you five apples, how many do you have?" In a world without zero, we have to assume everyone starts with some apples to begin with! So, for the same reasons having a zero lying around is important with numbers, it is handy to have a "generalized zero" hanging around with more abstract algebraic structures.
(Note this doesn't mean one or the other is "better" -- just that they are different, and the extra structure, when available, can come in handy. Also note that there is a universal way to turn a semigroup into a monoid by adding a zero element, so since all semigroup results lift into the 'completed' results on monoids, it tends to be more convenient, typically, to just treat things in terms of the latter.)
The empty Lego could be considered as id but then you will have to accept that empty space is Lego. But yes if you don't want id like #sclv wrote, it would be a semigroup.

TCL: check if variable is list

set var1 A
set var2 {A}
Is it possible to check if variable is list in TCL? For var1 and var2 llength gives 1. I am thinking that these 2 variables are considered same. They are both lists with 1 element. Am I right?
Those two things are considered to be entirely identical, and will produce identical bytecode (except for any byte offsets used for indicating where the content of constants are location, which is not information normally exposed to scripts at all so you can ignore it, plus the obvious differences due to variable names). Semantically, braces are a quoting mechanism and not an indicator of a list (or a script, or …)
You need to write your code to not assume that it can look things up by inspecting the type of a value. The type of 123 could be many different things, such as an integer, a list (of length 1), a unicode string or a command name. Tcl's semantics are based on you not asking what the type of a value is, but rather just using commands and having them coerce the values to the right type as required. Tcl's different to many other languages in this regard.
Because of this different approach, it's not easy to answer questions about this in general: the answers get too long with all the different possible cases to be considered in general yet most of it will be irrelevant to what you're really seeking to do. Ask about something specific though, and we'll be able to tell you much more easily.
You can try string is list $var1 but that will accept both of these forms - it will only return false on something that can't syntactically be interpreted as a list, eg. because there is an unmatched bracket like "aa { bb".