Typeclassopedia defines the Free monad data type.
data Free f a = Var a
| Node (f (Free f a))
Given:
class (MyMonad m) where
ret :: a -> m a
flatMap :: m a -> (a -> m b) -> m b
Here's my incomplete attempt at implementing the MyMonad instance of this typeclass.
instance Functor f => MyMonad (Free f) where
ret = Var
flatMap (Var x) f = f x
flatMap (Node xs) f = error
Please help me reason about what >>=/binding means over a Free monad.
When I struggled with implementing Applicative (Free f), I was encouraged to try to implement the Monad instance.
In these kinds of situations, typed holes can help with how to proceed. They give information about the type the still unimplemented "hole" should have.
Using a typed hole instead of error in your definition:
instance Functor f => MyMonad (Free f) where
ret = Var
flatMap (Var x) g = f x
flatMap (Node xs) g = _
Gives an error message like (here simplified):
Found hole `_' with type: Free f b
...
Relevant bindings include
g :: a -> Free f b (bound at Main.hs:10:21)
xs :: f (Free f a) (bound at Main.hs:10:17)
flatMap :: Free f a -> (a -> Free f b) -> Free f b
(bound at Main.hs:9:3)
That Free f b in the hole... which constructor should it have? Var or Node?
Now, a value of type Free a is like a tree that has values of type a on the leaves (the Var constructor) and whose branching nodes are "shaped" by the functor f.
What is >>= for Free? Think of it as taking a tree and "grafting" new trees on each of its leaves. These new trees are constructed from the values in the leaves using the function that is passed to >>=.
This helps us continue: now we know that the constructor on the right of the flatMap (Node xs) f = _ pattern must be Node, because "grafting" new things onto the tree never collapses already existing nodes into leaves, it only expands leaves into whole new trees.
Still using type holes:
instance Functor f => MyMonad (Free f) where
ret = Var
flatMap (Var x) g = f x
flatMap (Node xs) g = Node _
Found hole `_' with type: f (Free f b)
...
Relevant bindings include
g :: a -> Free f b (bound at Main.hs:10:21)
xs :: f (Free f a) (bound at Main.hs:10:17)
In xs we have a Free f a wrapped in a f, but f is a functor and we could easily map over it.
But how to convert that Free f a into the Free f b required by the hole? Intuitively, this Free f a will be "smaller" that the one the >>= started with, because we have stripped one "branching node". Maybe it is even a leaf node, like the case covered by the other pattern-match! This suggests using recursion of some kind.
Start by implementing the Functor instance. Then note that in general, a monad can be described as a functor that supports return and join :: m (m a) -> m a. Can you see how to implement join using =<< and return? Can you see how to implement =<< using fmap and join?
Spoilers
As you indicated,
data Free f a = Var a | Node (f (Free f a))
So (as you could work out with typed holes)
join :: Functor f => Free f (Free f a) -> Free f a
join (Var a) = a
join (Node m) = Node (fmap join m)
It might be useful to think about the geometry here. We descend the tree recursively, leaving the structure the same, until we get to the leaves, which we unwrap.
Note: =<< is the flipped version of >>=; it's more consistent with the other composition operators. $, <$>, <*>, ., =<<, and <=< all match up so you can read an expression using them from left to right or right to left without having to switch directions a few times in the middle.
Related
I have a Haskell exam in three days, so I thought I should practice a little and pulled up past exams, one of which features the following Tree datatype:
data Tree a = Leaf1 a | Leaf2 a a | Node (Tree a) (Maybe (Tree a)) deriving (Eq, Ord, Show)
It didn't seem that challenging at first, but then I realized I have to write a Traversable instance for this Tree. Dealing with the leaves were easy enough:
instance Traversable Tree where
traverse f (Leaf1 a) = Leaf1 <$> f a
traverse f (Leaf2 a b) = Leaf2 <$> f a <*> f b
However, I started running into problems with the Node.
traverse f (Node t Nothing) = Node <$> traverse f t <*> Nothing
traverse f (Node l (Just r)) = Node <$> traverse f l <*> Just (traverse f r)
Naturally, these don't work, and I can't wrap my head around what should come after the second <*>. I tried using holes, but the messages given to me by ghci didn't help much (I get that the problem is with types, but I have no idea how I'm supposed to fix it).
Here's the error message I got when I tried to compile it:
* Couldn't match type `f' with `Maybe'
`f' is a rigid type variable bound by
the type signature for:
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Tree a -> f (Tree b)
at exam.hs:92:3-10
Expected type: f (Maybe (Tree b))
Actual type: Maybe (Maybe (Tree b))
* In the second argument of `(<*>)', namely `Nothing'
In the expression: Node <$> traverse f t <*> Nothing
In an equation for `traverse':
traverse f (Node t Nothing) = Node <$> traverse f t <*> Nothing
* Relevant bindings include
f :: a -> f b (bound at exam.hs:94:12)
traverse :: (a -> f b) -> Tree a -> f (Tree b)
(bound at exam.hs:92:3)
|
94 | traverse f (Node t Nothing) = Node <$> traverse f t <*> Nothing
| ^^^^^^^
Could someone please give me some pointers or a possible fix for this issue?
The short answer is that you need to use traverse to get inside the Maybe.
The Traversable and Foldable instances for a type often have a similar structure to its Functor instance. Whereas fmap maps a pure function over a structure, combining the results back up with the pure constructors:
instance Functor Tree where
fmap f (Leaf1 a) = Leaf1 (f a)
fmap f (Leaf2 a1 a2) = Leaf2 (f a1) (f a2)
fmap f (Node ta mta) = Node (fmap f ta) (fmap (fmap f) mta)
Note the (fmap (fmap f) mta): the outer fmap maps over the Maybe, while the inner one maps over the Tree:
(fmap
:: (Tree a -> Tree b)
-> Maybe (Tree a) -> Maybe (Tree b))
((fmap
:: (a -> b)
-> Tree a -> Tree b)
f)
mta
traverse instead maps an effectful function over the structure, and correspondingly lifts the constructors into Applicative with the <$> and <*> operators:
instance Traversable Tree where
traverse f (Leaf1 a) = Leaf1 <$> f a
traverse f (Leaf2 a1 a2) = Leaf2 <$> f a1 <*> f a2
traverse f (Node ta mta) = Node <$> traverse f ta <*> traverse (traverse f) mta
Again, notice that we must traverse the Maybe, and within that, traverse the Tree, but instead of a pure function a -> b, we just have an effectful function a -> f b, given Applicative f:
(traverse
:: (Tree a -> f (Tree b))
-> Maybe (Tree a) -> f (Maybe (Tree b)))
((traverse
:: (a -> f b)
-> Tree a -> f (Tree b))
f)
mta
Likewise, foldMap has a similar structure, but instead of reconstructing the data type, it combines results using a Monoid instance:
instance Foldable Tree where
foldMap f (Leaf1 a) = f a
foldMap f (Leaf2 a1 a2) = f a1 <> f a2
foldMap f (Node ta mta) = foldMap f ta <> foldMap (foldMap f) mta
And here’s a simple example usage of traverse:
> traverse (\ x -> print x *> pure (x + 1)) (Node (Leaf1 10) (Just (Leaf2 20 30)))
10
20
30
Node (Leaf1 11) (Just (Leaf2 21 31))
With the DeriveFoldable, DeriveFunctor, and DeriveTraversable extensions, you may add a deriving (Foldable, Functor, Traversable) clause to a data type and use the -ddump-deriv flag of GHC to see the generated code.
traverse lets you apply a "function with an effect" to every "slot" of a data structure, maintaining the structure's shape. It has the type:
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
It relies crucially on the fact that the type of the "effects" is an Applicative. What operations does Applicatve provide?
it lets us lift pure functions and apply them to effectful actions with <$>.
it lets us combine effectful actions with (<*>) :: f (a -> b) -> f a -> f b. Notice that the second parameter is an effectful action, not a pure value.
it lets us take any pure value and put it in an effectful context, using pure :: a -> f a.
Now, when the node has a Nothing, there's no effect to perform because there aren't any values, but the <*> still requires an effectful action on the right. We can use pure Nothing to make the types fit.
When the node has a Just t, we can traverse the subtree t of type Tree a with the function a -> f b and end up with an action f (Tree b). But the <*> is actually expecting an f (Maybe (Tree b)). The lifted Node constructor makes us expect that. What can we do?
The solution is to lift the Just constructor into the action using <$>, which is another name for fmap.
Notice that we haven't changed the overall "shape" of the value: the Nothing is still Nothing, the Just is still Just. The structure of the subtrees didn't change either: we traversed them recursively but didn't modify them otherwise.
I have this F-Algebra (introduced in a previous question), and I want to cast an effectful algebra upon it. Through desperate trial, I managed to put together a monadic catamorphism that works. I wonder if it may be generalized to an applicative, and if not, why.
This is how I defined Traversable:
instance Traversable Expr where
traverse f (Branch xs) = fmap Branch $ traverse f xs
traverse f (Leaf i ) = pure $ Leaf i
This is the monadic catamorphism:
type AlgebraM a f b = a b -> f b
cataM :: (Monad f, Traversable a) => AlgebraM a f b -> Fix a -> f b
cataM f x = f =<< (traverse (cataM f) . unFix $ x)
And this is how it works:
λ let printAndReturn x = print x >> pure x
λ cataM (printAndReturn . evalSum) $ branch [branch [leaf 1, leaf 2], leaf 3]
1
2
3
3
6
6
My idea now is that I could rewrite like this:
cataA :: (Applicative f, Traversable a) => AlgebraM a f b -> Fix a -> f b
cataA f x = do
subtree <- traverse (cataA f) . unFix $ x
value <- f subtree
return value
Unfortunately, value here depends on subtree and, according to a paper on applicative do-notation, in such case we cannot desugar to Applicative. It seems like there's no way around this; we need a monad to float up from the depths of nesting.
Is it true? Can I safely conclude that only flat structures can be folded with applicative effects alone?
Can I safely conclude that only flat structures can be folded with applicative effects alone?
You can say that again! After all, "flattening nested structures" is exactly what makes a monad a monad, rather than Applicative which can only combine adjacent structures. Compare (a version of) the signatures of the two abstractions:
class Functor f => Applicative f where
pure :: a -> f a
(<.>) :: f a -> f b -> f (a, b)
class Applicative m => Monad m where
join :: m (m a) -> m a
What Monad adds to Applicative is the ability to flatten nested ms into one m. That's why []'s join is concat. Applicative only lets you smash together heretofore-unrelated fs.
It's no coincidence that the free monad's Free constructor contains a whole f full of Free fs, whereas the free applicative's Ap constructor only contains one Ap f.
data Free f a = Return a | Free (f (Free f a))
data Ap f a where
Pure :: a -> Ap f a
Cons :: f a -> Ap f b -> Ap f (a, b)
Hopefully that gives you some intuition as to why you should expect that it's not possible to fold a tree using an Applicative.
Let's play a little type tennis to see how it shakes out. We want to write
cataA :: (Traversable f, Applicative m) => (f a -> m a) -> Fix f -> m a
cataA f (Fix xs) = _
We have xs :: f (Fix f) and a Traversable for f. My first instinct here is to traverse the f to fold the contained subtrees:
cataA f (Fix xs) = _ $ traverse (cataA f) xs
The hole now has a goal type of m (f a) -> m a. Since there's an f :: f a -> m a knocking about, let's try going under the m to convert the contained fs:
cataA f (Fix xs) = _ $ fmap f $ traverse (cataA f) xs
Now we have a goal type of m (m a) -> m a, which is join. So you do need a Monad after all.
I am reading in the haskellbook about applicative and trying to understand it.
In the book, the author mentioned:
So, with Applicative, we have a Monoid for our structure and function
application for our values!
How is monoid connected to applicative?
Remark: I don't own the book (yet), and IIRC, at least one of the authors is active on SO and should be able to answer this question. That being said, the idea behind a monoid (or rather a semigroup) is that you have a way to create another object from two objects in that monoid1:
mappend :: Monoid m => m -> m -> m
So how is Applicative a monoid? Well, it's a monoid in terms of its structure, as your quote says. That is, we start with an f something, continue with f anotherthing, and we get, you've guessed it a f resulthing:
amappend :: f (a -> b) -> f a -> f b
Before we continue, for a short, a very short time, let's forget that f has kind * -> *. What do we end up with?
amappend :: f -> f -> f
That's the "monodial structure" part. And that's the difference between Applicative and Functor in Haskell, since with Functor we don't have that property:
fmap :: (a -> b) -> f a -> f b
-- ^
-- no f here
That's also the reason we get into trouble if we try to use (+) or other functions with fmap only: after a single fmap we're stuck, unless we can somehow apply our new function in that new structure. Which brings us to the second part of your question:
So, with Applicative, we have [...] function application for our values!
Function application is ($). And if we have a look at <*>, we can immediately see that they are similar:
($) :: (a -> b) -> a -> b
(<*>) :: f (a -> b) -> f a -> f b
If we forget the f in (<*>), we just end up with ($). So (<*>) is just function application in the context of our structure:
increase :: Int -> Int
increase x = x + 1
five :: Int
five = 5
increaseA :: Applicative f => f (Int -> Int)
increaseA = pure increase
fiveA :: Applicative f => f Int
fiveA = pure 5
normalIncrease = increase $ five
applicativeIncrease = increaseA <*> fiveA
And that's, I guessed, what the author meant with "function application". We suddenly can take those functions that are hidden away in our structure and apply them on other values in our structure. And due to the monodial nature, we stay in that structure.
That being said, I personally would never call that monodial, since <*> does not operate on two arguments of the same type, and an applicative is missing the empty element.
1 For a real semigroup/monoid that operation should be associative, but that's not important here
Although this question got a great answer long ago, I would like to add a bit.
Take a look at the following class:
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
Before explaining why we need some Monoidal class for a question about Applicatives, let us first take a look at its laws, abiding by which gives us a monoid:
f a (x) is isomorphic to f ((), a) (unit ** x), which gives us the left identity. (** unit) :: f a -> f ((), a), fmap snd :: f ((), a) -> f a.
f a (x) is also isomorphic f (a, ()) (x ** unit), which gives us the right identity. (unit **) :: f a -> f (a, ()), fmap fst :: f (a, ()) -> f a.
f ((a, b), c) ((x ** y) ** z) is isomorphic to f (a, (b, c)) (x ** (y ** z)), which gives us the associativity. fmap assoc :: f ((a, b), c) -> f (a, (b, c)), fmap assoc' :: f (a, (b, c)) -> f ((a, b), c).
As you might have guessed, one can write down Applicative's methods with Monoidal's and the other way around:
unit = pure ()
f ** g = (,) <$> f <*> g = liftA2 (,) f g
pure x = const x <$> unit
f <*> g = uncurry id <$> (f ** g)
liftA2 f x y = uncurry f <$> (x ** y)
Moreover, one can prove that Monoidal and Applicative laws are telling us the same thing. I asked a question about this a while ago.
In a recent assignment I have been asked to define fold functions for some non-list types. I'm still not quite able to wrap my head around this concept yet. Thus far, I have understood fold as performing over subsequent elements in the list. fold on Tree still do make intuitive sense, since one is able to apply some function recursively over the root's sub-trees.
However, on a datatype like:
Maybe a :: Nothing | Just a
There is no list (as it seems to me) to perform the fold action on.
I'm sure I have some issue with understanding the basic concepts here, and I would greatly appreciate some clearing up.
Foldable is a pretty confusing class, to be honest, because it doesn't have an awful lot of laws and it's quite possible to write quite a lot of different Foldable instances for almost any given type. Fortunately, it's possible to figure out what a Foldable instance should do in a purely mechanical way based on a Traversable instance for the same type—if there is one.
We have
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Traversable has several different laws, but it turns out the most important one is traverse Identity = Identity. Let's see how this applies to Maybe:
traverse :: Applicative f => (a -> f b) -> Maybe a -> f (Maybe b)
traverse g Nothing = _none
traverse g (Just a) = _some
Now in the first case, you need to produce f (Maybe b), and all you have is g :: a -> f b. Since you don't have any f values, and you don't have any a values, the only thing you can produce is pure Nothing.
In the second case, you have to produce f (Maybe b) and you have g :: a -> f b and a. So the only interesting way to start is to apply g to a, getting g a :: f b. Now you have two options to consider: you could throw away this value, and just return Nothing, or you can wrap it up in Just.
By the identity law, traverse Identity (Just a) = Identity (Just a). So you're not allowed to return Nothing. The only legal definition is
traverse _ Nothing = pure Nothing
traverse g (Just a) = Just <$> g a
The Traversable instance for Maybe is completely determined by the Traversable laws and parametricity.
Now it's possible to fold using traverse:
foldMapDefault :: (Traversable t, Monoid m)
=> (a -> m) -> t a -> m
foldMapDefault f xs =
getConst (traverse (Const . f) xs)
As this applies to Maybe,
foldMapDefault f Nothing =
getConst (traverse (Const . f) Nothing)
foldMapDefault f (Just a) =
getConst (traverse (Const . f) (Just a))
Expanding our definitions,
foldMapDefault f Nothing = getConst (pure Nothing)
foldMapDefault f (Just a) = getConst (Just <$> (Const (f a)))
By the definitions of pure and <$> for Const, these are
foldMapDefault f Nothing = getConst (Const mempty)
foldMapDefault f (Just a) = getConst (Const (f a))
Unwrapping the constructor,
foldMapDefault f Nothing = mempty
foldMapDefault f (Just a) = f a
And this is indeed exactly how foldMap is defined for Maybe.
As "basic concepts" go, this is pretty mind-bending, so don't feel too bad.
It may help to set aside your intuition about what a fold does to a list and think about what type a specific folding function (let's use foldr) should have if applied to a Maybe. Writing List a in place of [a] to make it clearer, the standard foldr on a list has type:
foldr :: (a -> b -> b) -> b -> List a -> b
Obviously, the corresponding fold on a Maybe must have type:
foldrMaybe :: (a -> b -> b) -> b -> Maybe a -> b
Think about what definition this could possibly have, given that it must be defined for all a and b without knowing anything else about the types. As a further hint, see if there's a function already defined in Data.Maybe that has a similar type -- maybe (ha ha) that'll give you some ideas.
According to several sources, the Haskell implementation for composing functors is more or less the following:
import Data.Functor.Compose
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
My question is: what is the type of x in the last definition?
I'd say it is f g a, but even there I struggle to 'see' the computation fmap (fmap f) x
Could anyone be as kind as to provide a clear and complete working example of this point? What about fmapping a Tree of Maybe's paying attention to both Empty's and Node's?
Thank you in advance.
what is the type of x in the last definition?
Before saying anything else about the matter: you can ask GHC! GHC 7.8 and above supports TypedHoles, meaning that if you place an underscore in a expression (not pattern), and hit load or compile, you get a message with the expected type of the underscore and the types of the variables in local scope.
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = _
GHC says now, with some parts omitted:
Notes.hs:6:26: Found hole ‘_’ with type: Compose f g b …
-- omitted type variable bindings --
Relevant bindings include
x :: f (g a)
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:21)
f :: a -> b
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:10)
fmap :: (a -> b) -> Compose f g a -> Compose f g b
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:5)
In the expression: _
In an equation for ‘fmap’: fmap f (Compose x) = _
In the instance declaration for ‘Functor (Compose f g)’
There you go, x :: f (g a). And after some practice, TypedHoles can help you tremendously in figuring out complex polymorphic code. Let's try to figure out our current code out by writing out the right hand side from scratch.
We've already seen that the hole had type Compose f g b. Therefore we must have a Compose _ on the right side:
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose _
The new hole has type f (g b). Now we should look at the context:
Relevant bindings include
x :: f (g a)
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:21)
f :: a -> b
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:10)
fmap :: (a -> b) -> Compose f g a -> Compose f g b
(bound at /home/kutta/home/Dropbox/src/haskell/Notes.hs:6:5)
The goal is to get an f (g b) out of the ingredients in the context. The fmap in the listing above unfortunately refers to the function being defined, which is sometimes helpful, but not here. We're better off knowing that f and g are both functors, therefore they can be fmap-ed over. Since we have x :: f (g a), we guess that we should fmap something over x to get an f (g b):
fmap f (Compose x) = Compose (fmap _ x)
Now the hole becomes g a -> g b. But g a -> g b is very easy now, since we have f :: a -> b and g is a Functor, so we also have fmap :: (a -> b) -> g a -> g b, and therefore fmap f :: g a -> g b.
fmap f (Compose x) = Compose (fmap (fmap f) x)
And we're done.
To wrap up the technique:
Start with putting a hole in the place where you don't know how to proceed. Here we started with putting the hole in place of the entire right hand side, but often you will have a good idea about most parts of an implementation and you'll need the hole in a specific problematic subexpression.
By looking at the types, try to narrow down which implementations could possibly lead to the goal and which could not. Fill in a new expression and reposition the hole. In proof assistant jargon this is called "refining".
Repeat step 2 until you either have the goal, in which case you're done, or the current goal seems impossible, in which case backtrack until the last non-obvious choice you made, and try an alternative refining.
The above technique is sometimes facetiously called "type tetris". A possible drawback is that you can implement complex code just by playing the "tetris", without actually understanding what you're doing. And sometimes after going too far, you get seriously stuck in the game, and then you have to start actually thinking about the problem. But ultimately it lets you understand code that would be otherwise very difficult to grasp.
I personally use TypedHoles all the time and basically as a reflex. I've come to rely so much on it so that on a occasion when I had to move back to GHC 7.6 I felt rather uncomfortable (but fortunately you can emulate holes even there).
The type of x is f (g a). For example, x might be a list of trees of integers: [Tree Int] (which can also be written as [] (Tree Int) so that it matches f (g x) more closely).
As an example, consider function succ :: Int -> Int which adds one to an integer. Then, function fmap succ :: Tree Int -> Tree Int will increment every integer in the tree. Further, fmap (fmap succ) :: [Tree Int] -> [Tree Int] will apply the previous fmap succ to all the trees in a list, hence it will increment every integer in the list of trees.
If instead you have Tree (Maybe Int), then fmap (fmap succ) will increment every integer in such tree. Values in the tree of the form Nothing will not be affected, while values Just x will have x incremented.
Example: (GHCi session)
> :set -XDeriveFunctor
> data Tree a = Node a (Tree a) (Tree a) | Empty deriving (Show, Functor)
> let x1 = [Node 1 Empty Empty]
> fmap (fmap succ) x1
[Node 2 Empty Empty]
> let x2 = [Node 1 Empty Empty, Node 2 (Node 3 Empty Empty) Empty]
> fmap (fmap succ) x2
[Node 2 Empty Empty,Node 3 (Node 4 Empty Empty) Empty]
> let x3 = Just (Node 1 Empty Empty)
> fmap (fmap succ) x3
Just (Node 2 Empty Empty)