Difference between type constructor and return function of a monad (in Haskell) - haskell

I'm trying to figure out monads in Haskell but didn't get too far yet.
I found https://en.wikibooks.org/wiki/Haskell/Understanding_monads#cite_note-1
and several other tutorials/explanations, but none seems to be explaining the difference between the type constructor and the return function.
As I understood the
type constructor constructs a monad from a given value of the basic data type. So it's sort of a normal constructor like in Java, which builds from the given parameter a new instance.
return function applies the type constructor on the given value of the basic data type and returns the constructed monad.
So what's the point of having two functions doing basically the same?
EDIT
So using the example of a Maybe-monad, the
country = Just "China": (constructor) creates the monad for the value "China".
return "China": returns the monad which is corresponding to the value of China, so it's basically the monad containing the "China" value.
Generally speaking I understand a monad as a container for values.
One usage of monads is to combine simple/existing computations to more complex computations.

Type constructors are type-level functions which return a type. Maybe is a type constructor which takes a single type parameter and returns a type e.g. Maybe String, Maybe Int etc.
data constructors are used to create values of a particular type. For some type Maybe a these constructors are Just and Nothing i.e.
data Maybe a = Just a | Nothing
The return function constructs a monadic value from a 'plain' value e.g.
return 1 :: Maybe Int
return "s" :: [String]
So in the definition of the Monad class
class Monad m where
return :: a -> m a
m is a type constructor e.g. (IO, Maybe, []) which is used to construct types, while return is a function which constructs a monadic value of type m a from a value of type a.
For the monad instance of Maybe, return constructs a value of Maybe a with just i.e.
instance Monad Maybe where
return x = Just x
so if you know you are dealing with Maybe it doesn't matter which you use. However, return has a more general type since it can be used to construct an arbitrary value m a for some monad m.

A type constructor constructs a type out of other types. It is not a function and has nothing to do with values.
In Haskell, [] is a type constructor. When applied to a type, say Int, it makes another type [Int].
Incidentally, in Java [] is a type constructor too. It can make a new type Int[] out of existing type Int.
Perhaps you wanted to ask about data constructors. Indeed, [] is also a data constructor (different from the type constructor spelled []) and in certain contexts it is equivalent to return. Why do we need return then? return works for any monad and can be used to write generic monadic code that works for any monad. It is a generalization of [] and Just and Left and...

In
(>>=) :: Monad m => m a -> (a -> m b) -> m b
m is a constructor of a type that is instance of the Monad class
m a is NOT a constructor application but a pattern matching to extract m and a
a->m b is a pattern against a function of m b. Let's call it k.
>>= needs to map to what k maps to ('returns'), i.e. apply k a
The implementation from Maybe
(Just x) >>= k = k x
In a do
>>= binds someMonad <- mConstructorSmartOrNot someParam to the next line
>> binds mConstructorSmartOrNot someParam to the next line
return :: Monad m => a -> m a
return is basically the same as m,
but since m can be any
constructor (of a value of a variable of an m-constructed type),
we can refer to it generally with this one name.
A monad constructs and forwards context.

Related

Clarification of Terms around Haskell Type system

Type system in haskell seem to be very Important and I wanted to clarify some terms revolving around haskell type system.
Some type classes
Functor
Applicative
Monad
After using :info I found that Functor is a type class, Applicative is a type class with => (deriving?) Functor and Monad deriving Applicative type class.
I've read that Maybe is a Monad, does that mean Maybe is also Applicative and Functor?
-> operator
When i define a type
data Maybe = Just a | Nothing
and check :t Just I get Just :: a -> Maybe a. How to read this -> operator?
It confuses me with the function where a -> b means it evaluates a to b (sort of returns a maybe) – I tend to think lhs to rhs association but it turns when defining types?
The term type is used in ambiguous ways, Type, Type Class, Type Constructor, Concrete Type etc... I would like to know what they mean to be exact
Indeed the word “type” is used in somewhat ambiguous ways.
The perhaps most practical way to look at it is that a type is just a set of values. For example, Bool is the finite set containing the values True and False.Mathematically, there are subtle differences between the concepts of set and type, but they aren't really important for a programmer to worry about. But you should in general consider the sets to be infinite, for example Integer contains arbitrarily big numbers.
The most obvious way to define a type is with a data declaration, which in the simplest case just lists all the values:
data Colour = Red | Green | Blue
There we have a type which, as a set, contains three values.
Concrete type is basically what we say to make it clear that we mean the above: a particular type that corresponds to a set of values. Bool is a concrete type, that can easily be understood as a data definition, but also String, Maybe Integer and Double -> IO String are concrete types, though they don't correspond to any single data declaration.
What a concrete type can't have is type variables†, nor can it be an incompletely applied type constructor. For example, Maybe is not a concrete type.
So what is a type constructor? It's the type-level analogue to value constructors. What we mean mathematically by “constructor” in Haskell is an injective function, i.e. a function f where if you're given f(x) you can clearly identify what was x. Furthermore, any different constructors are assumed to have disjoint ranges, which means you can also identify f.‡
Just is an example of a value constructor, but it complicates the discussion that it also has a type parameter. Let's consider a simplified version:
data MaybeInt = JustI Int | NothingI
Now we have
JustI :: Int -> MaybeInt
That's how JustI is a function. Like any function of the same signature, it can be applied to argument values of the right type, like, you can write JustI 5.What it means for this function to be injective is that I can define a variable, say,
quoxy :: MaybeInt
quoxy = JustI 9328
and then I can pattern match with the JustI constructor:
> case quoxy of { JustI n -> print n }
9328
This would not be possible with a general function of the same signature:
foo :: Int -> MaybeInt
foo i = JustI $ negate i
> case quoxy of { foo n -> print n }
<interactive>:5:17: error: Parse error in pattern: foo
Note that constructors can be nullary, in which case the injective property is meaningless because there is no contained data / arguments of the injective function. Nothing and True are examples of nullary constructors.
Type constructors are the same idea as value constructors: type-level functions that can be pattern-matched. Any type-name defined with data is a type constructor, for example Bool, Colour and Maybe are all type constructors. Bool and Colour are nullary, but Maybe is a unary type constructor: it takes a type argument and only the result is then a concrete type.
So unlike value-level functions, type-level functions are kind of by default type constructors. There are also type-level functions that aren't constructors, but they require -XTypeFamilies.
A type class may be understood as a set of types, in the same vein as a type can be seen as a set of values. This is not quite accurate, it's closer to true to say a class is a set of type constructors but again it's not as useful to ponder the mathematical details – better to look at examples.
There are two main differences between type-as-set-of-values and class-as-set-of-types:
How you define the “elements”: when writing a data declaration, you need to immediately describe what values are allowed. By contrast, a class is defined “empty”, and then the instances are defined later on, possibly in a different module.
How the elements are used. A data type basically enumerates all the values so they can be identified again. Classes meanwhile aren't generally concerned with identifying types, rather they specify properties that the element-types fulfill. These properties come in the form of methods of a class. For example, the instances of the Num class are types that have the property that you can add elements together.
You could say, Haskell is statically typed on the value level (fixed sets of values in each type), but duck-typed on the type level (classes just require that somebody somewhere implements the necessary methods).
A simplified version of the Num example:
class Num a where
(+) :: a -> a -> a
instance Num Int where
0 + x = x
x + y = ...
If the + operator weren't already defined in the prelude, you would now be able to use it with Int numbers. Then later on, perhaps in a different module, you could also make it usable with new, custom number types:
data MyNumberType = BinDigits [Bool]
instance Num MyNumberType where
BinDigits [] + BinDigits l = BinDigits l
BinDigits (False:ds) + BinDigits (False:es)
= BinDigits (False : ...)
Unlike Num, the Functor...Monad type classes are not classes of types, but of 1-ary type constructors. I.e. every functor is a type constructor taking one argument to make it a concrete type. For instance, recall that Maybe is a 1-ary type constructor.
class Functor f where
fmap :: (a->b) -> f a -> f b
instance Functor Maybe where
fmap f (Just a) = Just (f a)
fmap _ Nothing = Nothing
As you have concluded yourself, Applicative is a subclass of Functor. D being a subclass of C means basically that D is a subset of the set of type constructors in C. Therefore, yes, if Maybe is an instance of Monad it also is an instance of Functor.
†That's not quite true: if you consider the _universal quantor_ explicitly as part of the type, then a concrete type can contain variables. This is a bit of an advanced subject though.
‡This is not guaranteed to be true if the -XPatternSynonyms extension is used.

How to write this simple Monad?

I try to write this:
data A=A Int deriving Show
instance Monad A where
return x=A x
A x>>=f=f x
main=print a where a=A 1
I learn it from the book 《Learn You a Haskell for Great Good》:
instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f = f x
fail _ = Nothing
but got error:
a.hs:3:16: error:
? Expected kind ‘* -> *’, but ‘A’ has kind ‘*’
? In the first argument of ‘Monad’, namely ‘A’
In the instance declaration for ‘Monad A’
so how to write it? When finish, I can write
A 1>>\x->x+1
and get A 2
You can't make A an instance of Monad given its current definition.
The error message tells you that the compiler expects something of the kind * -> *. This means a type that takes a type as input, like Maybe a, IO a, or [] a. In other words, the type must be parametrically polymorphic.
In oder to get an intuitive sense of this, consider return, which has the type:
return :: a -> m a
The type argument a is unconstrained. This means that you should be able to take any value of type a and turn it into a value of the polymorphic type.
If I give you the Boolean value False, which A value will you construct from it? If I give you the string "foo", which A value will you construct from it? If I give you the function id, which A value will you construct from it?
If you want to make your type a Monad instance, you must give it a type parameter, at least like this:
data A a = A Int deriving Show
Here, the a type parameter is in the phantom role; it's not used, but now you're at least able to make it a Functor. This version of A is isomorphic to the Const functor. You can make it a Functor and Applicative instance, but can you make it a Monad?

Why is it said that typeclasses are existential?

According to this link describing existential types:
A value of an existential type like ∃x. F(x) is a pair containing some type x and a value of the type F(x). Whereas a value of a polymorphic type like ∀x. F(x) is a function that takes some type x and produces a value of type F(x). In both cases, the type closes over some type constructor F.
But a function definition with type class constraints doesn't pair with the type class instance.
It's not forall f, exists Functor f, ... (because it's obvious not every type f has instance of Functor f, hence exists Functor f ... not true).
It's not exists f and Functor f, ... (because it's applicable to all instances of satisfied f, not only the chosen one).
To me, it's forall f and instances of Functor f, ..., more like to scala's implicit arguments rather than existential types.
And according to this link describing type classes:
[The class declaration for Eq] means, logically, there is a type a for which the type a -> a -> Bool is inhabited, or, from a it can be proved that a -> a -> Bool (the class promises two different proofs for this, having names == and /=). This proposition is of existential nature (not to be confused with existential type)
What's the difference between type classes and existential types, and why are they both considered "existential"?
The wiki you quote is wrong, or at least being imprecise. A class declaration is not an existential proposition; it is not a proposition of any kind, it is merely a definition of a shorthand. One could then move on to making a proposition using that definition if you wanted, but on its own it's nothing like that. For example,
class Eq a where (==) :: a -> a -> Bool
makes a new definition. One could then write a non-existential, non-universal proposition using it, say,
Eq ()
which we could "prove" by writing:
instance Eq () where () == () = True
Or one could write
prop_ExistsFoo :: exists a. Eq a *> a
as an existential proposition. (Haskell doesn't actually have the exists proposition former, nor (*>). Think of (*>) as dual to (=>) -- just like exists is dual to forall. So where (=>) is a function which takes evidence of a constraint, (*>) is a tuple that contains evidence of a constraint, just like forall is for a function that takes a type while exists is for a tuple that contains a type.) We could "prove" this proposition by, e.g.
prop_ExistsFoo = ()
Note here that the type contained in the exists tuple is (); the evidence contained in the (*>) tuple is the Eq () instance we wrote above. I have honored Haskell's tendency to make types and instances silent and implicit here, so they don't appear in the visible proof text.
Similarly, we could make a different, universal proposition out of Eq by writing something like
prop_ForallEq :: forall a. Eq a => a
which is not nontrivially provable, or
prop_ForallEq2 :: forall a. Eq a => a -> a -> Bool
which we could "prove", for example, by writing
prop_ForallEq2 x y = not (x == y)
or in many other ways.
But the class declaration in itself is definitely not an existential proposition, and it doesn't have "existential nature", whatever that is supposed to mean. Instead of getting hung up and confused on that, please congratulate yourself for correctly labeling this incorrect claim as confusing!
The second quote is imprecise. The existential claim comes with the instances, not with the class itself. Consider the following class:
class Chaos a where
to :: a -> y
from :: x -> a
While this is a perfectly valid declaration, there can't possibly be any instances of Chaos (it there were, to . from would exist, which would be quite amusing). The type of, say, to...
GHCi> :t to
to :: Chaos a => a -> y
... tells us that, given any type a, if a is an instance of Chaos, there is a function which can turn an a into a value of any type whatsoever. If Chaos has no instances, that statement is vacuously true, so we can't infer the existence of any such function from it.
Putting classes aside for a moment, this situation is rather similar to what we have with the absurd function:
absurd :: Void -> a
This type says that, given a Void value, we can produce a value of any type whatsoever. That sounds, well, absurd -- but then we remember that Void is the empty type, which means there are no Void values, and it's all good.
For the sake of contrast, we might note that instances become possible once we break Chaos apart in two classes:
class Primordial a where
conjure :: a -> y
class Doom a where
destroy :: x -> a
instance Primordial Void where
conjure = absurd
instance Doom () where
destroy = const ()
When we, for example, write instance Primordial Void, we are claiming that Void is an instance of Primordial. That implies there must exist a function conjure :: Void -> y, at which point we must back up the claim by supplying an implementation.

What monadic type return return function

This function is strange. I'm confused.
return :: (Monad m) => a -> m a
If i wrote return 5, I will get monad with 5 inside. But what type? Typeclasses are only named dependencies, not types. Monad is List, IO ... but this is undefined monad type.
return is polymorphic so it can stand for more than one type. Just like + in C is overloaded to work both at summing ints and at summing floats, return is overloaded to work with any monad.
Of course, when its time to run the code you need to know what type the m corresponds to in order to know what concrete implementation of return to use. Some times you have explicit type annotations or type inference that lets you know what implementation of return to use
(return 5) :: [Int]
Other times, you can "push up" the decision higher up. If you write a larger polymorphic function, the inner returns use the same type from the outer function.
my_func :: Monad m => a -> m a
my_func x = return x
(my_func 10) :: [Int]
I told my func that I was working on the list monad and in turn, this made my_func use the list monad implementation of return inside.
Finally, if you don't leave enough information for the compiler to figure out what type to use, you will get an ambiguou intance compilation error. This is specially common with the Read typeclass. (try typing x <- readLn in ghci to see what happens...)
It's polymorphic. It returns whatever monad instance's return implementation was called. What specific data type it returns depends on the function.
[1,2,3] >>= \n -> return $ n + 1 -- Gives [2,3,4]
getLine >>= \str -> return $ reverse str -- Gets input and reverses it

Satisfying monad laws without a type constructor

Given e.g. a type like
data Tree a = Branch (Tree a) (Tree a)
| Leaf a
I can easily write instances for Functor, Applicative, Monad, etc.
But if the "contained" type is predetermined, e.g.
data StringTree = Branch StringTree StringTree
| Leaf String
I lose the ability to write these instances.
If I were to write functions for my StringTree type
stringTreeReturn :: String -> StringTree
stringTreeBind :: String -> (String -> StringTree) -> StringTree
stringTreeFail :: String -> StringTree
-- etc.
that satisfied the monad laws, could I still say that StringTree is a monad?
Tree a isn't a monad, either generally or for any particular a, Tree itself is a monad. A monad isn't a type, it's a correspondence between any type and a "monadic version" that type. For example, Integer is the type of integers, and Maybe Integer is the type of integers in the Maybe monad.
Consequently, StringTree, which is a type, can't be a monad. It's just not the same kind of thing. You can try to imagine it as the type of strings in a monad, but your functions stringTreeReturn, etc, don't match the types of their monadic correspondents. Look at the type of >>= in the Maybe monad:
Maybe a -> (a -> Maybe b) -> Maybe b
The second argument is a function from some a to any type in the Maybe monad (Maybe b). stringTreeBind has the type:
String -> (String -> StringTree) -> StringTree
The second argument can only be a function from String to the monadic version of String, rather than to the monadic version of any type.
Consequently, you can't do everything you can do to values in an arbitrary monadic type to StringTree values, which is why it can't be made an instance. Even if you could somehow get it treated as a monad, things would start going wrong when generic monadic code expects to be able to use generic monadic operations in ways that don't make sense for StringTree.
Ultimately, if you're thinking of it as "like" a monad because it's String in a container that can behave similarly to monadic containers, the easiest thing to do is simply make it a generic container of any type (Tree a). If you need have auxiliary functionality that depends specifically on it being a tree of strings, then you can write that code as operating only on Tree String values, and it will happily co-exist along with code that works generically on Tree a.
No. You're looking at the difference between a type and a kind. Simplistically, a kind is the way that Haskell classifies types, so it's a level of abstraction above types. ghci can help.
:type stringReturn
stringReturn :: String -> StringTree
:type Functor
<interactive>:1:1: Not in scope: data constructor `Functor'
So right off the bat, we can see that a function, which has a type, is an entirely different thing than a type, which has a kind.
We can also ask ghci about kinds.
:kind Functor
Functor (* -> *) -> Constraint
:kind StringTree
StringTree :: *
:kind Tree
Tree :: * -> *
Kinds use * for variables in their notation. We can see from the interaction above that Functor expects a type that is parameterized over one argument. We can also see that StringTree doesn't take any parameters, and Tree takes one.
That's a long way of expressing and unpacking your question, but hopefully it shows the difference between types and kinds.
No, that wouldn't be a monad. Think about it, can you write a monad m so only m String is ever possible?

Resources