Confusion regarding composition in Haskell - haskell

I'm working through the Haskell book and I've realized I'm having a hard time understanding function composition. At a very basic level I have a mental model of a pipeline that takes an input and passes it's result to the next function in the composition. For simple functions this is very easy.
Where I'm having difficulty is understanding how the resulting type signatures of composing the functions come to be. For example, if we look at the base definition of elem:
elem :: (Foldable t, Eq a) => a -> t a -> Bool
elem = any . (==)
>:t (==)
(==) :: Eq a => a -> a -> Bool
>:t any
any :: Foldable t => (a -> Bool) -> t a -> Bool
I fail to see how the resulting type signature occurs. If I were given the function and asked to write the type signature I'd be hopelessly lost.
The same goes for the following. In the chapter on Traversable we were told that traverse is just sequenceA and fmap composed:
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse f = sequenceA . fmap f
>:t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
>:t sequenceA
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
On their own I understand each functions type signature, but how do they combine to create traverse's type signature?
Super lost here, any help would be greatly appreciated.

Perhaps merely visually aligning the types will get you part of the way to some intuition about how the pipeline progresses, and help you make progress towards your next point of confusion!
(==) :: Eq a => a -> (a -> Bool)
any :: (a -> Bool) -> (t a -> Bool)
any . (==) :: Eq a => a -> (t a -> Bool)
To keep the next one on one screen, let's abbreviate Traversable to T and Applicative to A. You also have two fs in your question, one at the computation level and one at the type level. To avoid confusion, I'm going to rename your computation-level f to g instead. So if g :: a -> f b for some Applicative f:
fmap g :: T t => t a -> t (f b)
sequenceA :: (T t, A f) => t (f b) -> f (t b)
sequenceA . fmap g :: (T t, A f) => t a -> f (t b)
\g -> sequenceA . fmap g :: (T t, A f) => (a -> f b) -> t a -> f (t b)
(Wait! How come for fmap g, the constraint on t is Traversable and not Functor? Okay, no problem: we can actually give it the more relaxed type fmap g :: Functor t => .... But since every Traversable must be a Functor, it can also be given this type which makes the parallels more clear.)

All Haskell functions take just one argument -- even the ones we often think of as taking multiple arguments. Consider your elem example:
elem :: (Foldable t, Eq a) => a -> t a -> Bool
elem = any . (==)
>:t (==)
(==) :: Eq a => a -> a -> Bool
>:t any
any :: Foldable t => (a -> Bool) -> t a -> Bool
The type of (==) can be read as (==) :: Eq a => a -> (a -> Bool): it takes an a value (a can be anything which is an instance of Eq) and gives an a -> Bool function. any, in turn, takes an a -> Bool function (a can be anything) and gives a t a -> Bool function (t can be anything which is an instance of Foldable). That being so, the intermediate type in the any . (==) pipeline is Eq a => a -> Bool.

Related

When does GHCI not deduce the required context?

Why does GHCI add constraint for the required context here:
> let f = fmap show
> :t f
f :: (Functor f, Show a) => f a -> f String
But not here?
> :t over
over :: Lens s t a b -> (a -> b) -> s -> t
> :t _all'
_all' :: (Applicative f, Eq a) => a -> (a -> f a) -> [a] -> f [a]
> :t over (_all' 2)
<interactive>:1:7: error:
• Could not deduce (Applicative f) arising from a use of ‘_all'’
Is there any major difference between these two cases?
Note that isn't the type of over as defined by the lens library. That being said, your version doesn't work because Lens is
type Lens = forall f. Functor f => (a -> f b) -> s -> f t
and
_all' 2 :: forall f. Applicative f => ..
In other words, over is demanding a function which works for any Functor, but you've provided one which only works for Applicative (which is a stronger constraint, in that Functor doesn't imply Applicative).
Comment by #user2407038.
As alluded to in the comment, you can fix your problem by fixing the type signature for over. It should either be the complicated fancy thing in lens using distributive functors or the simpler
type Setter s t a b = (a -> Identity b) -> s -> Identity t
over :: Setter s t a b -> (a -> b) -> s -> t
As the identity type is both a functor and an applicative, it unifies with lenses and (I assume in your case) traversals.

Example of functions as applicatives, in foldMap and filter for foldables

In the first hunk, filterF is implemented with foldMap
import Data.List
pred :: a -> Bool
pred = undefined
wrapperOfA :: (Applicative f, Monoid (f a)) => a -> Bool -> f a
wrapperOfA a condition = if condition then pure a else mempty
-- foldMap :: (Foldable t, Monoid f a) => (a -> f a) -> t a -> f a
filterF :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a
filterF pred = foldMap ((<*>) wrapperOfA pred)
filterF (<3) [5,4,3,2,1] :: [Int]
-- [2,1]
... which utilises some Applicative's apply function, aka <*> typically infixed. Now, the type of <*> is:
:t (<*>)
--(<*>) :: forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
But replacing it with a hole gives its type as
-- (a0 -> Bool -> f0 a0) -> (a -> Bool) -> a -> f a
-- namely, from typechecking
filterF :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a
filterF pred = foldMap (_ wrapperOfA pred)
-- Found hole ‘_’ with type: (a0 -> Bool -> f0 a0) -> (a -> Bool) -> a -> f a
-- Where: ‘a’ is a rigid type variable bound by the type signature for interactive:IHaskell136.filterF :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a at :1:12
-- ‘f’ is a rigid type variable bound by the type signature for interactive:IHaskell136.filterF :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a at :1:12
-- ‘a0’ is an ambiguous type variable
-- ‘f0’ is an ambiguous type variable
-- Relevant bindings include
-- pred :: a -> Bool (bound at :2:9)
-- filterF :: (a -> Bool) -> t a -> f a (bound at :2:1)
-- In the expression: _
-- In the first argument of ‘foldMap’, namely ‘(_ wrapperOfA pred)’
-- In the expression: foldMap (_ wrapperOfA pred)
Basically, wrapperOfA does not look like f (a -> b) as <*> would imply, nor does pred look like type f a. Yet it works and type checks - why?
The (<*>) there uses the Applicative instance for functions. In...
-- Writing it infix, for the sake of clarity.
filterF pred = foldMap (wrapperOfA <*> pred)
... wrapperOfA has type a -> (Bool -> f a), and pred has type a -> Bool. That being so, wrapperOfA <*> pred has type a -> f a, as expected. If we substitute the implementation of (<*>) for functions (see the question linked to above for details), we get...
filterF pred = foldMap (\a -> wrapperOfA a (pred a))
... which makes it clear what is going on.
<*> uses the Applicative instance for functions
(<*>) :: f (a -> b) -> f a -> f b
where f is a (->) r , namely a function from the r domain.
Substituting, the first argument of <*> becomes a function from the r domain AND the a domain, then returning a b (a function of 2 arguments, since type r -> (a -> b) is equivalent to r -> a -> b), and the second argument becomes a function from the r domain returning an a.
To produce a (->) r b, we should apply the second-argument (a function) to the r parameter, and the resulting a is passed as a second argument to the thing in front of <*>. That is,
(<*>) wrapperOfA pred r = wrapperOfA r (pred r)
This leads me to a follow-up question/comment to bring the focus to foldMap and filterF which I now rename filterH.
filterH :: (a -> Bool) -> t a -> h a
foldMap :: (a -> f a) -> t a -> f a
wrapperOfA <*> pred :: a -> h a
where h is any applicative and monoid with corresponding pure and mempty but is as yet undefined. So I needed to request a return type eg ::[Int] in order for it to compile&evaluate. Can filterH be used without having to specify my own type h? Am I missing something in this solution?
This is a question from the textbook "haskell programming from first principles", in the foldables section.
Maybe you'll find easier this solution:
import Control.Conditional (select)
filterF :: (Applicative f, Foldable t, Monoid (f a)) => (a -> Bool) -> t a -> f a
filterF f = foldMap (select f pure mempty)
Here, select is just a functional if-then-else, where you provide functions for the condition, the true case and the else case.

Traversable#mapM & sequence - Necessary?

Typeclassopedia presents Traversable:
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
sequenceA :: Applicative f => t (f a) -> f (t a)
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
sequence :: Monad m => t (m a) -> m (t a)
A good exercise is to figure out what the default implementations should be: given either traverse or sequenceA, how would you define the other three methods?
I came up with the following code that type-checks:
class (Functor t, Foldable t) => MyTraversable t where
traverse' :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse' = error "..."
sequenceA' :: Applicative f => t (f a) -> f (t a)
sequenceA' f = traverse' id f
mapM :: Monad m => (a -> m b) -> t a -> m (t b)
mapM = traverse'
sequence' :: Monad m => t (m a) -> m (t a)
sequence' = sequenceA'
If my implementations of mapM and sequence' are correct, and, since every Monad is an Applicative:
λ: :i Monad
class Applicative m => Monad (m :: * -> *) where
...
then it's not clear to me why mapM and sequence' are even necessary. Why are they?
P.S. - Credit and my thanks to haoformayor for helping me out with sequenceA.
As mentioned in the comments, there was a time when not every Monad was an Applicative.
Just recently (in base-4.8 which shipped with GHC 7.10) the Applicative was made a superclass of Monad. You might have seen Applicative-Monad-Proposal, AMP.
Currently the Monad of no return, MRP (email-thread) is worked on, which will make
Monad's >> and Applicative's *> the same. Which eventlually would make possible to say that traverse = mapM and sequence = sequenceA. But that is a long process, which will take time.
So to answer your question: for history reasons.

Haskell lenses: how to make view play nicely with traverse?

I am trying to learn about lenses by implementing it in Haskell. I have implemented the view combinator as follows:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Data.Traversable
type Lens s a = Functor f => (a -> f a) -> s -> f s
view :: Lens s a -> s -> a
view lens = getConst . lens Const
However when I try to use it in conjunction with traverse I get the following error message:
Prelude> :load Lens.hs
[1 of 1] Compiling Main ( Lens.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t view traverse
<interactive>:1:6:
Could not deduce (Applicative f) arising from a use of ‘traverse’
from the context (Traversable t)
bound by the inferred type of it :: Traversable t => t a -> a
at Top level
or from (Functor f)
bound by a type expected by the context:
Functor f => (a -> f a) -> t a -> f (t a)
at <interactive>:1:1-13
Possible fix:
add (Applicative f) to the context of
a type expected by the context:
Functor f => (a -> f a) -> t a -> f (t a)
or the inferred type of it :: Traversable t => t a -> a
In the first argument of ‘view’, namely ‘traverse’
In the expression: view traverse
Unfortunately, I don't understand this error message. Please explain what it means and how I may fix it.
As the other answers already explain, the issue is that view expects something that works for any Functor f, but traverse only works if f is also Applicative (and there are functors which are not applicative).
In lens, the problem is solved by making the type of view not take a Rank2 argument (in fact, most functions in lens don't use the Lens type synonym, they always use something weaker). For your function, observe that view only ever uses f ~ Const. This is why you can change the type signature to:
view :: ((a -> Const a a) -> s -> Const a s) -> s -> a
The implementation can stay the same, but now view also works on traverse:
view traverse :: (Traversable t, Monoid a) => t a -> a
Note the extra Monoid constraint. This constraint appears because if you set f ~ Const a in traverse :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a), you need an instance Applicative (Const a). That instance has a Monoid constraint on a though. And this also makes sense, because the traversable might be empty or contain more than one element, so you need mempty and mappend.
tl;dr - According to your definition of Lens, a traverse cannot be a Lens because traverse doesn't work for all Functors.
Let's take a look at your types:
λ :set -XRankNTypes
λ :m +Control.Applicative Data.Traversable
λ type Lens s a = Functor f => (a -> f a) -> s -> f s
λ :t traverse
traverse
:: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
Now at this point we can see that traverse is, in one way, slightly more general than our Lens type - it can take a function
from a -> f b where our lens can only take functions from a -> f a.
Restricting it to that case is no problem, so we can say
λ :t traverse :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a)
traverse :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a)
:: (Applicative f, Traversable t) => (a -> f a) -> t a -> f (t a)
So now it's obvious that if traverse is to be a Lens, it must be a Lens (t a) a, since that's the only way to make the type variables line up.
So let's try that out.
λ :t traverse :: Lens (t a) a
<interactive>:1:1:
Could not deduce (Traversable t1) arising from a use of `traverse'
from the context (Functor f)
bound by the inferred type of
it :: Functor f => (a -> f a) -> t a -> f (t a)
at Top level
or from (Functor f1)
bound by an expression type signature:
Functor f1 => (a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
at <interactive>:1:1-24
Possible fix:
add (Traversable t1) to the context of
an expression type signature:
Functor f1 => (a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
or the inferred type of
it :: Functor f => (a -> f a) -> t a -> f (t a)
In the expression: traverse :: Lens (t a) a
Oof, it didn't like that. Oh, wait, in order to use traverse our type t has to be Traversable, so let's add that restriction. (Just like the "Possible fix") suggests:
λ :t traverse :: Traversable t => Lens (t a) a
<interactive>:1:1:
Could not deduce (Applicative f1) arising from a use of `traverse'
from the context (Functor f, Traversable t)
bound by the inferred type of
it :: (Functor f, Traversable t) => (a -> f a) -> t a -> f (t a)
at Top level
or from (Traversable t1, Functor f1)
bound by an expression type signature:
(Traversable t1, Functor f1) =>
(a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
at <interactive>:1:1-41
Possible fix:
add (Applicative f1) to the context of
an expression type signature:
(Traversable t1, Functor f1) =>
(a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
or the inferred type of
it :: (Functor f, Traversable t) => (a -> f a) -> t a -> f (t a)
In the expression: traverse :: Traversable t => Lens (t a) a
Ok, so the problem now is that it can't infer that f is Applicative (which is also required to use traverse), just that it's a Functor (which it gets from the definition of Lens).
We can't add Applicative f to the context though - the f is hidden. When we say type Lens s a = Functor f => (a -> f a) -> s -> f s, we're saying that the Lens has to work for all Functors.
But traverse only works for the subset of Functors that are also Applicative. So in this way the type of traverse is more specific than is allowed for Lenses.
traverse has this type:
traverse :: (Applicative f, Traversable t) => (x -> f y) -> t x -> f (t y)
If we make the free variable f in the type definition of Lens explicit, its definition is actually
type Lens s a = forall f . Functor f => (a -> f a) -> s -> f s
So view wants a function that can operate on any Functor, whereas traverse can only operate on an Applicative.
You can fix the error simply by changing Functor into Applicative in the definition of Lens, but I'm not sure if that's exactly what you would want to achieve here.

How to implement this Traversable use pattern?

When use Data.Traversable I frequently requires some code like
import Control.Applicative (Applicative,(<*>),pure)
import Data.Traversable (Traversable,traverse,sequenceA)
import Control.Monad.State (state,runState)
traverseF :: Traversable t => ((a,s) -> (b,s)) -> (t a, s) -> (t b, s)
traverseF f (t,s) = runState (traverse (state.curry f) t) s
to traverse the structure and build up a new one driven by some state. And I notice the type signature pattern and believe it could be able to generalized as
fmapInner :: (Applicative f,Traversable t) => (f a -> f b) -> f (t a) -> f (t b)
fmapInner f t = ???
But I fail to implement this with just traverse, sequenceA, fmap, <*> and pure. Maybe I need stronger type class constrain? Do I absolutely need a Monad here?
UPDATE
Specifically, I want to know if I can define fmapInner for a f that work for any Traversable t and some laws for intuition applied (I don't know what the laws should be yet), is it imply that the f thing is a Monad? Since, for Monads the implementation is trivial:
--Monad m implies Applicative m but we still
-- have to say it unless we use mapM instead
fmapInner :: (Monad m,Traversable t) => (m a -> m b) -> m (t a) -> m (t b)
fmapInner f t = t >>= Data.Traversable.mapM (\a -> f (return a))
UPDATE
Thanks for the excellent answer. I have found that my traverseF is just
import Data.Traversable (mapAccumL)
traverseF1 :: Traversable t => ((a, b) -> (a, c)) -> (a, t b) -> (a, t c)
traverseF1 =uncurry.mapAccumL.curry
without using Monad.State explicitly and have all pairs flipped. Previously I though it was mapAccumR but it is actually mapAccumL that works like traverseF.
I've now convinced myself that this is impossible. Here's why,
tF ::(Applicative f, Traversable t) => (f a -> f b) -> f (t a) -> f (t b)
So we have this side-effecting computation that returns t a and we want to use this to determine what side effects happen. In other words, the value of type t a will determine what side effects happen when we apply traverse.
However this isn't possible possible with the applicative type class. We can dynamically choose values, but the side effects of out computations are static. To see what I mean,
pure :: a -> f a -- No side effects
(<*>) :: f (a -> b) -> f a -> f b -- The side effects of `f a` can't
-- decide based on `f (a -> b)`.
Now there are two conceivable ways to determine side effects at depending on previous values,
smash :: f (f a) -> f a
Because then we can simply do
smash $ (f :: a -> f a) <$> (fa :: f a) :: f a
Now your function becomes
traverseF f t = smash $ traverse (f . pure) <$> t
Or we can have
bind :: m a -> (a -> m b) -> m b -- and it's obvious how `a -> m b`
-- can choose side effects.
and
traverseF f t = bind t (traverse $ f . pure)
But these are join and >>= respectively and are members of the Monad typeclass. So yes, you need a monad. :(
Also, a nice, pointfree implementation of your function with monad constraints is
traverseM = (=<<) . mapM . (.return)
Edit,
I suppose it's worth noting that
traverseF :: (Applicative f,Traversable t) => (f a -> f b) -> t a -> f (t a)
traverseF = traverse . (.pure)

Resources