Given two monads, Monad m and Monad n, I would like to transform m (n a) into n (m a). But there seems to be no generic way because both (>>=) and return deals with only one monad type, and although (>>=) allows extracting content from a monad, you must pack them back to the same monad type so it can be a result value.
However, if we set m to a fixed type, the job becomes easy. Take Maybe as an example:
reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
x' <- x
return $ Just x'
Or a list:
reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
x' <- x
xs' <- reorder xs
return (x':xs')
Not hard to see, we've got a pattern here. To be more obvious, write it in a Applicative way, and it's no more than applying the data constructor to each element:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
My question is: does a haskell typeclass already exist to describe such operations, or do I have to invent the wheel myself?
I had a brief search in the GHC documentation, and found nothing useful for this topic.
Data.Traversable provides what you are looking for:
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
GHC even provides support for automatically deriving instances:
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
import Data.Foldable
import Data.Traversable
data List a = Nil | Cons a (List a)
deriving(Functor, Foldable, Traversable)
A quick search on hoogle for (Monad m, Monad n) => m (n a) -> n (m a) showed me that there are several functions that (roughly) comply with the signature you're looking for:
Data.Traversable.sequence :: (Traversable t, Monad m) => t (m a) -> m (t a);
Data.Traversable.sequenceA :: Applicative f => t (f a) -> f (t a);
Contro.Monad.sequence :: Monad m => [m a] -> m [a] (also exported by Prelude).
Both [a] and Maybe a are instances of traversable, so your reorder functions are just applications of Data.Traversable.sequence. One could write, in example:
ghci> (Data.Traversable.sequence $ Just (return 1)) :: IO (Maybe Int)
Just 1
it :: Maybe Int
ghci> (Data.Traversable.sequence $ Just ([1])) :: [Maybe Int]
[Just 1]
it :: [Maybe Int]
ghci> (Data.Traversable.sequence $ [Just 1]) :: Maybe [Int]
Just [1]
it :: Maybe [Int]
Please note however that the specific class declaration is class (Functor t, Foldable t) => Traversable t, and if you look also at the types of the other two functions, it does not seems like what you're looking for could possibly be done in a generic way for all monads m and n without restrictions/preconditions.
It can't be done in general: a good example of a monad that can't do this is the reader (or function) monad. That would require the following function to be definable:
impossible :: (r -> IO a) -> IO (r -> a)
It's not straightforward to prove that a function cannot be implemented. But intuitively, the problem is that whatever IO has to be done in the value returned has to be done before we know what the r parameter is. So impossible readFile would have to yield a pure function FilePath -> String before it knew which files to open. Clearly, at least, impossible can't do what you'd want it to.
Not all Monads can commute in that way. Edward Kmett's distributive package provides a typeclass Distributive for type constructors that is similar to what you desire (simplified):
class Functor g => Distributive g where
distribute :: Functor f => f (g a) -> g (f a)
collect :: Functor f => (a -> g b) -> f a -> g (f b)
Default definitions are provided for distribute and collect, written in terms of each other. I found this package by searching hayoo for the desired type signature.
Related
I am trying to understand Traversable with the help of https://namc.in/2018-02-05-foldables-traversals.
Somewhere the author mentioned the following sentence:
Traversable is to Applicative contexts what Foldable is to Monoid
values.
What did he try to clarify?
I do not get the connection between Foldable to Monoid.
Please provide an example.
In the beginning, there was foldr:
foldr :: (a -> b -> b) -> b -> [a] -> b
and there was mapM:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
foldr was generalized to data types other than [a] by letting each type define its own definition of foldr to describe how to reduce it to a single value.
-- old foldr :: (a -> b -> b) -> b -> [] a -> b
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
If you have a monoid, you don't have to specify a binary function, because the Monoid instance already provides its own starting value and knows how to combine two values, which is apparent from its default definition in terms of foldr:
-- If m is a monoid, it provides its own function of type b -> b.
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty
Traverse does the same kind of generalization from lists to traversable types, but for mapM:
-- old mapM :: Monad m => (a -> m b) -> [] a -> m ([] b)
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
(When mapM was first defined, there was no Applicative class; if there had been, mapA :: Applicative f => (a -> f b) -> [a] -> f [b] could have been defined instead; the Monad constraint was stronger than was necessary.)
An Applicative is monoidal in nature, so there was no need in Traverse for the type of distinction that foldr/foldMap draws.
The article (and the corresponding passage of the Wikibook) is talking about how the effects (or, to use the language seen there, the contexts) of applicative values can be combined monoidally. The connection with Foldable is that list-like folding is ultimately amounts to combining values monoidally (see chepner's answer, and also Foldr/Foldl for free when Tree is implementing Foldable foldmap?. As for the applicative contexts part, there are a few ways to look at that. One of them is noting that, for any Applicative f and Monoid m, f m is a monoid, with pure mempty as mempty and liftA2 mappend as mappend (this Ap type from the reducers package witnesses that). For a concrete example, let's pick f ~ Maybe and m ~ (). That leaves us with four possible combinations:
liftA2 mappend (Just ()) (Just ()) = Just ()
liftA2 mappend (Just ()) Nothing = Nothing
liftA2 mappend Nothing (Just ()) = Nothing
liftA2 mappend Nothing Nothing = Nothing
Now contrast with All, the Bool monoid with (&&) as mappend:
mappend (All True) (All True) = All True
mappend (All True) (All False) = All False
mappend (All False) (All True) = All False
mappend (All False) (All False) = All False
They match perfectly: Just () stands for True, Nothing for False, and liftA2 mappend for (&&).
Now let's have another look at the Wikibook example:
deleteIfNegative :: (Num a, Ord a) => a -> Maybe a
deleteIfNegative x = if x < 0 then Nothing else Just x
rejectWithNegatives :: (Num a, Ord a, Traversable t) => t a -> Maybe (t a)
rejectWithNegatives = traverse deleteIfNegative
GHCi> rejectWithNegatives [2,4,8]
Just [2,4,8]
GHCi> rejectWithNegatives [2,-4,8]
Nothing
The Maybe values generated by applying deleteIfNegative to the values in the lists are combined monoidally in the way shown above, so that we get a Nothing unless all the Maybe values are Just.
This matter can also be approached in the opposite direction. Through the Applicative instance for Const...
-- I have suppressed a few implementation details from the instance used by GHC.
instance Monoid m => Applicative (Const m) where
pure _ = Const mempty
Const x <*> Const y = Const (x `mappend` y)
... we can get an Applicative out of any Monoid, such that (<*>) combines the monoidal values monoidally. That makes it possible to define foldMap and friends in terms of traverse.
On a final note, the category theoretical description of Applicative as a class for monoidal functors involves something rather different from what I have covered here. For further discussion of this issue, and of other fine print, see Monoidal Functor is Applicative but where is the Monoid typeclass in the definition of Applicative? (if you want to dig deeper, it is well worth it to read all of the answers there).
I'm learning haskell, and trying to use applicative functors as much as possible instead of monad. It is very neat and easy to compose. However, occasionally some types like IO [IO [a]] or IO Maybe IO Maybe a will rise in the code, which cause me big trouble. Apparently monad become inevitable in these scenarios.
I know there is a flat operation like join:: m (m a) -> m a for single level monads. Is there anything similar for multi-level monads? Anything in monad transformers?
Thanks a lot!
If you note that m (n _) is a monad transformer then you can define this operation. This is certainly the case when we notice that IO (Maybe a) is the same as MaybeT IO a: we then just use MaybeT's join. We can do this in no small part due to the fact that Maybe and IO "layer" especially nicely.
On the other hand, not all "composed" monads are monad transformers. In particular, IO [a] isn't really one. The true ListT transformer we'd like to have and to join looks like
newtype ListT m a = ListT { runListT :: m (Maybe (a, ListT m a)) }
It is the case that we can turn IO [a] into ListT IO a and visa-versa, but it is not the case that these operations invert one another. Truly, IO [a] is not a monad in its own right and cannot be joined.
Monads do not commute in general, but you can provide all particular cases, that you need:
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Monad
class (Monad m, Monad n) => Swappable m n where
swap :: m (n a) -> n (m a)
instance Swappable [] IO where
swap = sequence
instance Swappable Maybe IO where
swap Nothing = return Nothing
swap (Just mx) = fmap return mx
cut :: Swappable m n => m (n (m a)) -> n (m a)
cut = liftM join . swap
squash :: Swappable m n => n (m (n (m a))) -> n (m a)
squash = (>>= cut)
An example:
x :: IO [IO [()]]
x = return $ map (\s -> putStrLn s >> return [()]) ["ab","c"]
y :: IO (Maybe (IO (Maybe ())))
y = return $ Just $ putStrLn "z" >> return (Just ())
main = squash x >> squash y
prints
ab
c
z
EDIT
You can avoid defining new typeclass by providing an instance of Traversable (there are instances for Maybe and [] in Data.Traversable):
import Data.Traversable as T
import Control.Monad
cut :: (Traversable t, Monad t, Monad m) => t (m (t a)) -> m (t a)
cut = liftM join . T.sequence
squash :: (Traversable t, Monad t, Monad m) => m (t (m (t a))) -> m (t a)
squash = (>>= cut)
Foldable is a superclass of Traversable, similarly to how Functor is a superclass of Applicative and Monad.
Similar to the case of Monad, where it is possible to basically implement fmap as
liftM :: Monad m => (a->b) -> m a -> m b
liftM f q = return . f =<< q
we could also emulate foldMap as
foldLiftT :: (Traversable t, Monoid m) => (a -> m) -> t a -> m
foldLiftT f = fst . traverse (f >>> \x -> (x,x))
-- or: . sequenceA . fmap (f >>> \x -> (x, x))
using the Monoid m => (,) m monad. So the combination of superclass and methods bears in both cases a certain redundancy.
In case of monads, it can be argued that a “better” definition of the type class would be (I'll skip applicative / monoidal)
class (Functor m) => Monad m where
return :: a -> m a
join :: m (m a) -> m a
at least that's what's used in category theory. This definition does, without using the Functor superclass, not permit liftM, so it is without this redundancy.
Is a similar transformation possible for the Traversable class?
To clarify: what I'm after is a re-definition, let's call it,
class (Functor t, Foldable t) => Traversable t where
skim :: ???
such that we could make the actual Traverse methods top-level functions
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
but it would not be possible to make generically
instance (Traversable t) => Foldable t where
foldMap = ... skim ...
data T
instance Traversable T where
skim = ...
I'm not asking because I need this for something particular; it's a conceptual question so as to better understand the difference between Foldable and Traversable. Again much like Monad vs Functor: while >>= is much more convenient than join for everyday Haskell programming (because you usually need precisely this combination of fmap and join), the latter makes it simpler to grasp what a monad is about.
Foldable is to Functor as Traversable is to Monad, i.e. Foldable and Functor are superclasses of Monad and Traversable (modulo all the applicative/monad proposal noise).
Indeed, that's already in the code
instance Foldable f => Traversable f where
...
So, it's not clear what more there is to want. Foldable is characterized by toList :: Foldable f => f a -> [a] while Traversable depends ultimately on not only being able to abstract the content as a list like toList does, but also to be able to extract the shape
shape :: Functor f => f a -> f ()
shape = fmap (const ())
and then recombine them
combine :: Traversable f => f () -> [a] -> Maybe (f a)
combine f_ = evalStateT (traverse pop f_) where
pop :: StateT [a] Maybe a
pop = do x <- get
case x of
[] = empty
(a:as) = set as >> return a
which depends on traverse.
For more information on this property see this blog post by Russell O'Connor.
Super hand-wavy because it's late, but the extra power that Traversable has over Foldable is a way to reconstruct the original structure. For example, with lists:
module MyTraverse where
import Data.Foldable
import Data.Traversable
import Control.Applicative
import Data.Monoid
data ListRec f x = ListRec
{ el :: f (Endo [x])
}
instance Applicative f => Monoid (ListRec f x) where
mempty = ListRec (pure mempty)
mappend (ListRec l) (ListRec r) =
ListRec (mappend <$> l <*> r)
toM :: Functor f => f b -> ListRec f b
toM this = ListRec $ (Endo . (:)) <$> this
fromM :: Functor f => ListRec f b -> f [b]
fromM (ListRec l) = flip appEndo [] <$> l
myTraverse :: Applicative f => (a-> f b) -> [a] -> f [b]
myTraverse f xs = fromM $ foldMap (toM . f) xs
I think this myTraverse behaves the same as traverse, using only the classes Applicative, Foldable, and Monoid. You could re-write it to use foldr instead of foldMap if you wanted to get rid of Monoid.
lists are easy because they're a flat structure. However, I strongly suspect that you could use a Zipper to get the proper reconstruction function for any structure (since zippers are generically derivable, they should always exists).
But even with a zipper, you don't have any way of indicating that structure to the monoid/function. Notionally, it seems Traversable adds something like
class Traversed t where
type Path t :: *
annotate :: t a -> [(Path t, a)]
fromKeyed :: [(Path t, a)] -> t a
this seems to overlap heavily with Foldable, but I think that's inevitable when trying to associate the paths with their constituent values.
I want to map over Applicative form.
The type of map-like function would be like below:
mapX :: (Applicative f) => (f a -> f b) -> f [a] -> f [b]
used as:
result :: (Applicative f) => f [b]
result = mapX f xs
where f :: f a -> f b
f = ...
xs :: f[a]
xs = ...
As the background of this post, I try to write fluid simulation program using Applicative style referring to Paul Haduk's "The Haskell School of Expression", and I want to express the simulation with Applicative style as below:
x, v, a :: Sim VArray
x = x0 +: integral (v * dt)
v = v0 +: integral (a * dt)
a = (...calculate acceleration with x v...)
instance Applicative Sim where
...
where Sim type means the process of simulation computation and VArray means Array of Vector (x,y,z). X, v a are the arrays of position, velocity and acceleration, respectively.
Mapping over Applicative form comes when definining a.
I've found one answer to my question.
After all, my question is "How to lift high-order functions (like map
:: (a -> b) -> [a] -> [b]) to the Applicative world?" and the answer
I've found is "To build them using lifted first-order functions."
For example, the "mapX" is defined with lifted first-order functions
(headA, tailA, consA, nullA, condA) as below:
mapX :: (f a -> f b) -> f [a] -> f [b]
mapX f xs0 = condA (nullA xs0) (pure []) (consA (f x) (mapA f xs))
where
x = headA xs0
xs = tailA xs0
headA = liftA head
tailA = liftA tail
consA = liftA2 (:)
nullA = liftA null
condA b t e = liftA3 aux b t e
where aux b t e = if b then t else e
First, I don't think your proposed type signature makes much sense. Given an applicative list f [a] there's no general way to turn that into [f a] -- so there's no need for a function of type f a -> f b. For the sake of sanity, we'll reduce that function to a -> f b (to transform that into the other is trivial, but only if f is a monad).
So now we want:
mapX :: (Applicative f) => (a -> f b) -> f [a] -> f [b]
What immediately comes to mind now is traverse which is a generalization of mapM. Traverse, specialized to lists:
traverse :: (Applicative f) => (a -> f b) -> [a] -> f [b]
Close, but no cigar. Again, we can lift traverse to the required type signature, but this requires a monad constraint: mapX f xs = xs >>= traverse f.
If you don't mind the monad constraint, this is fine (and in fact you can do it more straightforwardly just with mapM). If you need to restrict yourself to applicative, then this should be enough to illustrate why you proposed signature isn't really possible.
Edit: based on further information, here's how I'd start to tackle the underlying problem.
-- your sketch
a = liftA sum $ mapX aux $ liftA2 neighbors (x!i) nbr
where aux :: f Int -> f Vector3
-- the type of "liftA2 neighbors (x!i) nbr" is "f [Int]
-- my interpretation
a = liftA2 aux x v
where
aux :: VArray -> VArray -> VArray
aux xi vi = ...
If you can't write aux like that -- as a pure function from the positions and velocities at one point in time to the accelerations, then you have bigger problems...
Here's an intuitive sketch as to why. The stream applicative functor takes a value and lifts it into a value over time -- a sequence or stream of values. If you have access to a value over time, you can derive properties of it. So velocity can be defined in terms of acceleration, position can be defined in terms of velocity, and soforth. Great! But now you want to define acceleration in terms of position and velocity. Also great! But you should not need, in this instance, to define acceleration in terms of velocity over time. Why, you may ask? Because velocity over time is all acceleration is to begin with. So if you define a in terms of dv, and v in terms of integral(a) then you've got a closed loop, and your equations are not propertly determined -- either there are, even given initial conditions, infinitely many solutions, or there are no solutions at all.
If I'm thinking about this right, you can't do this just with an applicative functor; you'll need a monad. If you have an Applicative—call it f—you have the following three functions available to you:
fmap :: (a -> b) -> f a -> f b
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
So, given some f :: f a -> f b, what can you do with it? Well, if you have some xs :: [a], then you can map it across: map (f . pure) xs :: [f b]. And if you instead have fxs :: f [a], then you could instead do fmap (map (f . pure)) fxs :: f [f b].1 However, you're stuck at this point. You want some function of type [f b] -> f [b], and possibly a function of type f (f b) -> f b; however, you can't define these on applicative functors (edit: actually, you can define the former; see the edit). Why? Well, if you look at fmap, pure, and <*>, you'll see that you have no way to get rid of (or rearrange) the f type constructor, so once you have [f a], you're stuck in that form.
Luckily, this is what monads are for: computations which can "change shape", so to speak. If you have a monad m, then in addition to the above, you get two extra methods (and return as a synonym for pure):
(>>=) :: m a -> (a -> m b) -> m b
join :: m (m a) -> m a
While join is only defined in Control.Monad, it's just as fundamental as >>=, and can sometimes be clearer to think about. Now we have the ability to define your [m b] -> m [b] function, or your m (m b) -> m b. The latter one is just join; and the former is sequence, from the Prelude. So, with monad m, you can define your mapX as
mapX :: Monad m => (m a -> m b) -> m [a] -> m [b]
mapX f mxs = mxs >>= sequence . map (f . return)
However, this would be an odd way to define it. There are a couple of other useful functions on monads in the prelude: mapM :: Monad m => (a -> m b) -> [a] -> m [b], which is equivalent to mapM f = sequence . map f; and (=<<) :: (a -> m b) -> m a -> m b, which is equivalent to flip (>>=). Using those, I'd probably define mapX as
mapX :: Monad m => (m a -> m b) -> m [a] -> m [b]
mapX f mxs = mapM (f . return) =<< mxs
Edit: Actually, my mistake: as John L kindly pointed out in a comment, Data.Traversable (which is a base package) supplies the function sequenceA :: (Applicative f, Traversable t) => t (f a) => f (t a); and since [] is an instance of Traversable, you can sequence an applicative functor. Nevertheless, your type signature still requires join or =<<, so you're still stuck. I would probably suggest rethinking your design; I think sclv probably has the right idea.
1: Or map (f . pure) <$> fxs, using the <$> synonym for fmap from Control.Applicative.
Here is a session in ghci where I define mapX the way you wanted it.
Prelude>
Prelude> import Control.Applicative
Prelude Control.Applicative> :t pure
pure :: Applicative f => a -> f a
Prelude Control.Applicative> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude Control.Applicative> let mapX fun ma = pure fun <*> ma
Prelude Control.Applicative> :t mapX
mapX :: Applicative f => (a -> b) -> f a -> f b
I must however add that fmap is better to use, since Functor is less expressive than Applicative (that means that using fmap will work more often).
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
edit:
Oh, you have some other signature for mapX, anyway, you maybe meant the one I suggested (fmap)?
According to the Typeclassopedia (among other sources), Applicative logically belongs between Monad and Pointed (and thus Functor) in the type class hierarchy, so we would ideally have something like this if the Haskell prelude were written today:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Pointed f where
pure :: a -> f a
class Pointed f => Applicative f where
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
-- either the traditional bind operation
(>>=) :: (m a) -> (a -> m b) -> m b
-- or the join operation, which together with fmap is enough
join :: m (m a) -> m a
-- or both with mutual default definitions
f >>= x = join ((fmap f) x)
join x = x >>= id
-- with return replaced by the inherited pure
-- ignoring fail for the purposes of discussion
(Where those default definitions were re-typed by me from the explanation at Wikipedia, errors being my own, but if there are errors it is at least in principle possible.)
As the libraries are currently defined, we have:
liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM :: (Monad m) => (a -> b) -> m a -> m b
and:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap :: (Monad m) => m (a -> b) -> m a -> m b
Note the similarity between these types within each pair.
My question is: are liftM (as distinct from liftA) and ap (as distinct from <*>), simply a result of the historical reality that Monad wasn't designed with Pointed and Applicative in mind? Or are they in some other behavioral way (potentially, for some legal Monad definitions) distinct from the versions that only require an Applicative context?
If they are distinct, could you provide a simple set of definitions (obeying the laws required of Monad, Applicative, Pointed, and Functor definitions described in the Typeclassopedia and elsewhere but not enforced by the type system) for which liftA and liftM behave differently?
Alternatively, if they are not distinct, could you prove their equivalence using those same laws as premises?
liftA, liftM, fmap, and . should all be the same function, and they must be if they satisfy the functor law:
fmap id = id
However, this is not checked by Haskell.
Now for Applicative. It's possible for ap and <*> to be distinct for some functors simply because there could be more than one implementation that satisfies the types and the laws. For example, List has more than one possible Applicative instance. You could declare an applicative as follows:
instance Applicative [] where
(f:fs) <*> (x:xs) = f x : fs <*> xs
_ <*> _ = []
pure = repeat
The ap function would still be defined as liftM2 id, which is the Applicative instance that comes for free with every Monad. But here you have an example of a type constructor having more than one Applicative instance, both of which satisfy the laws. But if your monads and your applicative functors disagree, it's considered good form to have different types for them. For example, the Applicative instance above does not agree with the monad for [], so you should really say newtype ZipList a = ZipList [a] and then make the new instance for ZipList instead of [].
They can differ, but they shouldn't.
They can differ because they can have different implementations: one is defined in an instance Applicative while the other is defined in an instance Monad. But if they indeed differ, then I'd say the programmer who wrote those instances wrote misleading code.
You are right: the functions exist as they do for historical reasons. People have strong ideas about how things should have been.