I'm working through the Brent Yorgey Haskell course, and I'm having trouble defining a good instance for Applicative. A parser is defined as follows:
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
The function takes a string, parses a certain amount of input, and returns a Maybe tuple where the first value is the type of the parser, and the rest is the unparsed remainder of the string. For example, this is a parser for positive integers:
posInt :: Parser Integer
posInt = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit xs
The assignment is to make an Applicative instance for Parser. We start with a Functor instance (which is relatively straight-forward, I think):
first :: (a -> b) -> (a,c) -> (b,c)
first f (a, c) = (f a, c)
instance Functor Parser where
fmap f p = Parser f'
where f' s = fmap (first f) $ (runParser p) s
And then I tried my hand with Applicative:
collapse (Just (Just a)) = Just a
collapse _ = Nothing
extract (Just a, Just b) = Just (a,b)
extract _ = Nothing
appliedFunc :: Parser (a->b) -> Parser a -> String -> Maybe (b, String)
appliedFunc p1 p2 str = extract (f <*> fmap fst result2, fmap snd result2)
where result1 = (runParser p1) str
f = fmap fst result1
result2 = collapse $ fmap (runParser p2) $ fmap snd result1
instance Applicative Parser where
pure a = Parser (\s -> Just (a, s))
p1 <*> p2 = Parser (appliedFunc p1 p2)
...yuck. So my question is, how can I make my Applicative instance cleaner and less difficult to read? I feel like there's an easy answer for this question, but I haven't been able to wrap my head around the types just yet.
I assume you haven't got to Monads in the course yet. The way you are using collapse and fmap indicate to me that you are essentially reinventing Monads to solve this problem, and in particular the Monad Maybe instance. In fact your collapse is the same as join for this monad. And indeed using that is a very elegant way to solve this problem, but perhaps somewhat "cheating" at this point. The following is the best shape I could get it into while using your functions:
appliedFunc p1 p2 str = collapse $ fmap step1 (runParser p1 str)
where
step1 (f, str2) = collapse $ fmap step2 (runParser p2 str2)
where
step2 (x, str3) = Just (f x, str3)
Once you get to Monads proper, you should be able to rewrite this with the even more succinct (>>=) operator and/or do notation.
Another alternative which is almost as simple, but doesn't require reinventing monads, is to use explicit pattern matching of the Maybes. Then you can get something like:
appliedFunc p1 p2 str = case runParser p1 str of
Nothing -> Nothing
Just (f, str2) -> case runParser p2 str2 of
Nothing -> Nothing
Just (x, str3) -> Just (f x, str3)
This is probably not what you want, but I wanted to mention in passing that there is a really succinct way to implement this:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Applicative
import Control.Monad.Trans.State
newtype Parser a = Parser { unParser :: StateT String Maybe a }
deriving (Functor, Applicative, Monad, Alternative)
runParser :: Parser a -> String -> Maybe (a, String)
runParser = runStateT . unParser
parser :: (String -> Maybe (a, String)) -> Parser a
parser = Parser . StateT
The reason this works is that under the hood StateT is implemented as:
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
If you specialize s to String and specialize m to Maybe, you get:
StateT String Maybe a ~ String -> Maybe (a, String)
... which is the same as your type.
StateT has the following instances provided automatically for you:
instance Monad m => Functor (StateT s m)
instance Monad m => Applicative (StateT s m)
instance Monad m => Monad (StateT s m)
instance Alternative m => Alternative (StateT s m)
... and we can specialize m in those instances to Maybe because Maybe implements both Alternative and Monad:
instance Monad Maybe
instance Alternative Maybe
... so that means that StateT s Maybe is automatically a Functor, Applicative, Monad and Alternative without any additional work on our part.
The last part of the trick is GeneralizedNewtypeDeriving, which lets us lift type class instances through a newtype wrapper. Since our underlying StateT type is a Functor, Applicative, Monad, and Alternative, we can automatically lift all four type class instances through our newtype by adding:
... deriving (Functor, Applicative, Monad, Alternative)
... and the compiler will reimplement them for our newtype, taking care to do all the newtype wrapping and unwrapping for us.
So if you want to figure out how to implement Applicative for your parser, you may want to study how Applicative is implemented for StateT and then deduce from that how to implement it for your parser type.
Related
I have the following pattern of a Reader with a Semigroup Element:
runFunction :: Reader Env Element
runFunction = do
a <- getA
b <- getB
c <- getC
return $ a <> b <> c
Where getA :: Reader Env Element.
Is there a way to:
runFunction = do
getA
getB
getC
I feel like I see this pattern alot, where I imperatively chain monadic calls, and they get turned into a single element at the end.
Note: I don't want to do getA >>= getB >>= getC since getB isn't :: Element -> Reader Env Element
It feels like a State Monad, that automatically modifies state with <>, but I don't know.
Working with monadic code is still quite fresh to me.
The WriterT monad transformer can be used to build up a monoidal value with each action.
You can use lift to wrap your Reader actions into the WriterT monad transformer, then move the result of each action into the monad's environment by using tell, sequence the actions, and then unwrap the result back to a single Reader action using execWriterT.
Here is what I mean:
import Control.Monad.Writer
wrap :: (Monad m, Monoid w) => m w -> WriterT w m ()
wrap m = lift m >>= tell
unwrap :: (Monad m) => WriterT w m a -> m w
unwrap = execWriterT
runFunction :: Reader Env Element
runFunction = unwrap $ do
wrap getA
wrap getB
wrap getC
As you can see, this generalizes to any monad, not just Reader.
runFunction = fmap mconcat . sequence $ [getA, getB, getC]
whatever the monad is.
fmap mconcat . sequence
:: (Monoid b, Monad f, Traversable t) => t (f b) -> f b
List, [], is a Traversable.
With Semigroups, there's sconcat.
I looked hard to see if this may be a duplicate question but couldn't find anything that addressed specifically this. My apologies if there actually is something.
So, I get how lift works, it lifts a monadic action (fully defined) from the outer-most transformer into the transformed monad. Cool.
But what if I want to apply a (>>=) from one level under the transformer into the transformer? I'll explain with an example.
Say MyTrans is a MonadTrans, and there is also an instance Monad m => Monad (MyTrans m). Now, the (>>=) from this instance will have this signature:
instance Monad m => Monad (MyTrans m) where
(>>=) :: MyTrans m a -> (a -> MyTrans m b) -> MyTrans m b
but what I need is something like this:
(>>=!) :: Monad m => MyTrans m a -> (m a -> MyTrans m b) -> MyTrans m b
In general:
(>>=!) :: (MonadTrans t, Monad m) => t m a -> (m a -> t m b) -> t m b
It looks like a combination of the original (>>=) and lift, except it really isn't. lift can only be used on covariant arguments of type m a to transform them into a t m a, not the other way around. In other words, the following has the wrong type:
(>>=!?) :: Monad m => MyTrans m a -> (a -> m b) -> MyTrans m b
x >>=!? f = x >>= (lift . f)
Of course a general colift :: (MonadTrans t, Monad m) => t m a -> m a makes absolutely zero sense, because surely the transformer is doing something that we cannot just throw away like that in all cases.
But just like (>>=) introduces contravariant arguments into the monad by ensuring that they will always "come back", I thought something along the lines of the (>>=!) function would make sense: Yes, it in some way makes an m a from a t m a, but only because it does all of this within t, just like (>>=) makes an a from an m a in some way.
I've thought about it and I don't think (>>=!) can be in general defined from the available tools. In some sense it is more than what MonadTrans gives. I haven't found any related type classes that offer this either. MFunctor is related but it is a different thing, for changing the inner monad, but not for chaining exclusively transformer-related actions.
By the way, here is an example of why you would want to do this:
EDIT: I tried to present a simple example but I realized that that one could be solved with the regular (>>=) from the transformer. My real example (I think) cannot be solved with this. If you think every case can be solved with the usual (>>=), please do explain how.
Should I just define my own type class for this and give some basic implementations? (I'm interested in StateT, and I'm almost certain it can be implemented for it) Am I doing something in a twisted way? Is there something I overlooked?
Thanks.
EDIT: The answer provided by Fyodor matches the types, but does not do what I want, since by using pure, it is ignoring the monadic effects of the m monad. Here is an example of it giving the wrong answer:
Take t = StateT Int and m = [].
x1 :: StateT Int [] Int
x1 = StateT (\s -> [(1,s),(2,s),(3,s)])
x2 :: StateT Int [] Int
x2 = StateT (\s -> [(1,s),(2,s),(3,s),(4,s))])
f :: [Int] -> StateT Int [] Int
f l = StateT (\s -> if (even s) then [] else (if (even (length l)) then (fmap (\z -> (z,z+s)) l) else [(123,123)]))
runStateT (x1 >>= (\a -> f (pure a))) 1 returns [(123,123),(123,123),(123,123)] as expected, since both 1 is odd and the list in x1 has odd length.
But runStateT (x2 >>= (\a -> f (pure a))) 1 returns [(123,123),(123,123),(123,123),(123,123)], whereas I would have expected it to return [(1,2),(2,3),(3,4),(4,5)], since the 1 is odd and the length of the list is even. Instead, the evaluation of f is happening on the lists [(1,1)], [(2,1)], [(3,1)] and [(4,1)] independently, due to the pure call.
This can be very trivially implemented via bind + pure. Consider the signature:
(>>=!) :: (Monad m, MonadTrans t) => t m a -> (m a -> t m a) -> t m a
If you use bind on the first argument, you get yourself a naked a, and since m is a Monad, you can trivially turn that naked a into an m a via pure. Therefore, the straightforward implementation would be:
(>>=!) x f = x >>= \a -> f (pure a)
And because of this, bind is always strictly more powerful than your proposed new operation (>>=!), which is probably the reason it doesn't exist in the standard libraries.
I think it may be possible to propose more clever interpretations of (>>=!) for some specific transformers or specific underlying monads. For example, if m ~ [], one might imagine passing the whole list as m a instead of its elements one by one, as my generic implementation above would do. But this sort of thing seems too specific to be implemented in general.
If you have a very specific example of what you're after, and you can show that my above general implementation doesn't work, then perhaps I can provide a better answer.
Ok, to address your actual problem from the comments:
I have a function f :: m a -> m b -> m c that I want to transform into a function ff :: StateT s m a -> StateT s m b -> StateT s m c
I think looking at this example may illustrate the difficulty better. Consider the required signature:
liftish :: Monad m => (m a -> m b -> m c) -> StateT m a -> StateT m b -> StateT m c
Presumably, you'd want to keep the effects of m that are already "imprinted" within the StateT m a and StateT m b parameters (because if you don't - my simple solution above will work). To do this, you can "unwrap" the StateT via runStateT, which will get you m a and m b respectively, which you can then use to obtain m c:
liftish f sa sb = do
s <- get
let ma = fst <$> runStateT sa s
mb = fst <$> runStateT sb s
lift $ f ma mb
But here's the trouble: see those fst <$> in there? They are throwing away the resulting state. The call to runStateT sa s results not only in the m a value, but also in the new, modified state. And same goes for runStateT sb s. And presumably you'd want to get the state that resulted from runStateT sa and pass it to runStateT sb, right? Otherwise you're effectively dropping some state mutations.
But you can't get to the resulting state of runStateT sa, because it's "wrapped" inside m. Because runStateT returns m (a, s) instead of (m a, s). If you knew how to "unwrap" m, you'd be fine, but you don't. So the only way to get that intermediate state is to run the effects of m:
liftish f sa sb = do
s <- get
(c, s'') <- lift $ do
let ma = runStateT sa s
(_, s') <- ma
let mb = runStateT sb s'
(_, s'') <- mb
c <- f (fst <$> ma) (fst <$> mb)
pure (c, s'')
put s''
pure c
But now see what happens: I'm using ma and mb twice: once to get the new states out of them, and second time by passing them to f. This may lead to double-running effects or worse.
This problem of "double execution" will, I think, show up for any monad transformer, simply because the transformer's effects are always wrapped inside the underlying monad, so you have a choice: either drop the transformer's effects or execute the underlying monad's effects twice.
I think what you "really want" is
(>>>==) :: MyTrans m a -> (forall b. m b -> MyTrans n b) -> MyTrans n a
-- (=<<) = flip (>>=) is nicer to think about, because it shows that it's a form of function application
-- so let's think about
(==<<<) :: (forall a. m b -> MyTrans n b) -> (forall a. MyTrans m a -> MyTrans n a)
-- hmm...
type (~>) a b = forall x. a x -> b x
(==<<<) :: (m ~> MyTrans n) -> MyTrans m ~> MyTrans n
-- look familiar?
That is, you are describing monads on the category of monads.
class MonadTrans t => MonadMonad t where
-- returnM :: m ~> t m
-- but that's just lift, therefore the MonadTrans t superclass
-- note: input must be a monad homomorphism or else all bets are off
-- output is also a monad homomorphism
(==<<<) :: (Monad m, Monad n) => (m ~> t n) -> t m ~> t n
instance MonadMonad (StateT s) where
-- fairly sure this is lawful
-- EDIT: probably not
f ==<<< StateT x = do
(x, s) <- f <$> x <$> get
x <$ put s
However, making your example work is just not going to happen. It is too unnatural. StateT Int [] is the monad for programs that nondeterministically evolve the state. It is an important property of that monad that each "parallel universe" receives no communication from the others. The specific operation you are performing will probably not be provided by any useful typeclass. You can only do part of it:
f :: [] ~> StateT Int []
f l = StateT \s -> if odd s && even (length l) then fmap (\x -> (x, s)) l else []
f ==<<< x1 = []
f ==<<< x2 = [(1,1),(2,1),(3,1),(4,1)]
Background. In one of my classes we've been exploring the Parser monad. The Parser monad is typically defined as either
newtype Parser a = Parser (String -> [(a, String)])
Or as
newtype Parser a = Parser (String -> Maybe (a, String))
In either case, we can instance Parser as a Functor using code that works in both cases:
instance Functor Parser where
fmap f (Parser p) = Parser (fmap applyF . p)
where applyF (result, s) = (f result, s)
If we have a Parser built to return Maybe (a, String), this applies f to the result if the result exists. And if we have a Parser built to return [(a, String)], this applies f to each of the results returned in the list.
We can instance Applicative, Monad, MonadPlus, and Alternative is similarly generic ways (so that they work either for Maybe or []).
Question. If I parameterize Parser based on the type used to wrap the result, how can I instance it for Functor and friends?
newtype Parser m a = Parser (String -> m (a, String))
-- How do I instance `Parser` as a Functor if `m` is a Functor?
You can here construct a constraint that m should be a type that is an instance of Functor as well, and then fmap on that result:
instance Functor m => Functor (Parser m) where
fmap f (Parser p) = Parser (\x -> fmap g (p x))
where g (r, s) = (f r, s)
Here g is thus a function that performs the mapping f on the first element of the tuple. We thus use that g as a "mapping" function over the result.
This will thus work for any m that is an instance of Functor, like a Maybe, a [], a Tree, etc.
I have a bunch of data structures like data Foo = Foo {a :: Type1, b :: Type2} deriving (Something) with Type1 and Type2 being always different (generally primitive types but it's irrelevant) and in different numbers.
I came to have a bunch of functions like
justFooify :: Maybe Type1 -> Maybe Type2 -> Maybe Foo
justFooify f b =
| isNothing f = Nothing
| isNothing b = Nothing
| otherwise = Just $ Foo (fromJust f) (fromJust b)
Is there something I'm missing? After the third such function I wrote I came to think that maybe it could be too much.
You need applicatives!
import Control.Applicative
justFooify :: Maybe Type1 -> Maybe Type2 -> Maybe Foo
justFooify f b = Foo <$> f <*> b
Or you can use liftA2 in this example:
justFooify = liftA2 Foo
It acts like liftM2, but for Applicative. If you have more parameters, just use more <*>s:
data Test = Test String Int Double String deriving (Eq, Show)
buildTest :: Maybe String -> Maybe Int -> Maybe Double -> Maybe String -> Maybe Test
buildTest s1 i d s2 = Test <$> s1 <*> i <*> d <*> s2
What are Applicatives? They're basically a more powerful Functor and a less powerful Monad, they fall right in between. The definition of the typeclass is
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
-- plus a few more things that aren't important right now
If your Applicative is also a Monad, then pure is the same as return (in fact, some people feel that having return is incorrect, we should only have pure). The <*> operator is what makes them more powerful than Functors, though. It gives you a way to put a function in your data structure, then apply that function to values also wrapped in your data structure. So when you have something like
> :t Test -- Our construct
Test :: String -> Int -> Double -> String -> Test
> :t fmap Test -- also (Test <$>), since (<$>) = fmap
fmap Test :: Functor f => f String -> f (Int -> Double -> String -> Test)
We see that it constructs a function inside of a Functor, since Test takes multiple arguments. So Test <$> Just "a" has the type Maybe (Int -> Double -> String -> Test). With just Functor and fmap, we can't apply anything to the inside of that Maybe, but with <*> we can. Each application of <*> applies one argument to that inner Functor, which should now be considered an Applicative.
Another handy thing about it is that it works with all Monads (that currently define their Applicative instance). This means lists, IO, functions of one argument, Either e, parsers, and more. For example, if you were getting input from the user to build a Test:
askString :: IO String
askInt :: IO Int
askDouble :: IO Double
-- whatever you might put here to prompt for it, or maybe it's read from disk, etc
askForTest :: IO Test
askForTest = Test <$> askString <*> askInt <*> askDouble <*> askString
And it'd still work. This is the power of Applicatives.
FYI, in GHC 7.10 there will be implemented the Functor-Applicative-Monad Proposal. This will change the definition of Monad from
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
to
class Applicative m => Monad m where
return :: a -> m a
return = pure
(>>=) :: m a -> (a -> m b) -> m b
join :: m (m a) -> m a
(more or less). This will break some old code, but many people are excited for it as it will mean that all Monads are Applicatives and all Applicatives are Functors, and we'll have the full power of these algebraic objects at our disposal.
I am trying to parse a file using the parseFile function found in the the haskell-src-exts package.
I am trying to work with the output of parseFile which is of course IO, but I can't figure out how to get around the IO. I found a function liftIO but I am not sure if that is the solution in this situation. Here is the code below.
import Language.Haskell.Exts.Syntax
import Language.Haskell.Exts
import Data.Map hiding (foldr, map)
import Control.Monad.Trans
increment :: Ord a => a -> Map a Int -> Map a Int
increment a = insertWith (+) a 1
fromName :: Name -> String
fromName (Ident s) = s
fromName (Symbol st) = st
fromQName :: QName -> String
fromQName (Qual _ fn) = fromName fn
fromQName (UnQual n) = fromName n
fromLiteral :: Literal -> String
fromLiteral (Int int) = show int
fromQOp :: QOp -> String
fromQOp (QVarOp qn) = fromQName qn
vars :: Exp -> Map String Int
vars (List (x:xs)) = vars x
vars (Lambda _ _ e1) = vars e1
vars (EnumFrom e1) = vars e1
vars (App e1 e2) = unionWith (+) (vars e1) (vars e2)
vars (Let _ e1) = vars e1
vars (NegApp e1) = vars e1
vars (Var qn) = increment (fromQName qn) empty
vars (Lit l) = increment (fromLiteral l) empty
vars (Paren e1) = vars e1
vars (InfixApp exp1 qop exp2) =
increment (fromQOp qop) $
unionWith (+) (vars exp1) (vars exp2)
match :: [Match] -> Map String Int
match rhss = foldr (unionWith (+) ) empty
(map (\(Match a b c d e f) -> rHs e) rhss)
rHS :: GuardedRhs -> Map String Int
rHS (GuardedRhs _ _ e1) = vars e1
rHs':: [GuardedRhs] -> Map String Int
rHs' gr = foldr (unionWith (+)) empty
(map (\(GuardedRhs a b c) -> vars c) gr)
rHs :: Rhs -> Map String Int
rHs (GuardedRhss gr) = rHs' gr
rHs (UnGuardedRhs e1) = vars e1
decl :: [Decl] -> Map String Int
decl decls = foldr (unionWith (+) ) empty
(map fun decls )
where fun (FunBind f) = match f
fun _ = empty
pMod' :: (ParseResult Module) -> Map String Int
pMod' (ParseOk (Module _ _ _ _ _ _ dEcl)) = decl dEcl
pMod :: FilePath -> Map String Int
pMod = pMod' . liftIO . parseFile
I just want to be able to use the pMod' function on the output of parseFile.
Note that all the types and data constructors can be found at http://hackage.haskell.org/packages/archive/haskell-src-exts/1.13.5/doc/html/Language-Haskell-Exts-Syntax.html if that helps. Thanks in advance!
Once inside IO, there's no escape.
Use fmap:
-- parseFile :: FilePath -> IO (ParseResult Module)
-- pMod' :: (ParseResult Module) -> Map String Int
-- fmap :: Functor f => (a -> b) -> f a -> f b
-- fmap pMod' (parseFile filePath) :: IO (Map String Int)
pMod :: FilePath -> IO (Map String Int)
pMod = fmap pMod' . parseFile
(addition:) As explained in great answer by Levi Pearson, there's also
Prelude Control.Monad> :t liftM
liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
But that's no black magic either. Consider:
Prelude Control.Monad> let g f = (>>= return . f)
Prelude Control.Monad> :t g
g :: (Monad m) => (a -> b) -> m a -> m b
So your function can also be written as
pMod fpath = fmap pMod' . parseFile $ fpath
= liftM pMod' . parseFile $ fpath
= (>>= return . pMod') . parseFile $ fpath -- pushing it...
= parseFile fpath >>= return . pMod' -- that's better
pMod :: FilePath -> IO (Map String Int)
pMod fpath = do
resMod <- parseFile fpath
return $ pMod' resMod
whatever you find more intuitive (remember, (.) has the highest precedence, just below the function application).
Incidentally, the >>= return . f bit is how liftM is actually implemented, only in do-notation; and it really shows the equivalency of fmap and liftM, because for any monad it should hold that:
fmap f m == m >>= (return . f)
To give a more general answer than Will's (which was certainly correct and to-the-point), you typically 'lift' operations into a Monad rather than taking values out of them in order to apply pure functions to monadic values.
It so happens that Monads (theoretically) are a specific kind of Functor. Functor describes the class of types that represent mappings of objects and operations into a different context. A data type that is an instance of Functor maps objects into its context via its data constructors and it maps operations into its context via the fmap function. To implement a true functor, fmap must work in such a way that lifting the identity function into the functor context does not change the values in the functor context, and lifting two functions composed together produces the same operation within the functor context as lifting the functions separately and then composing them within the functor context.
Many, many Haskell data types naturally form functors, and fmap provides a universal interface to lift functions so that they apply 'evenly' throughout the functorized data without worrying about the form of the particular Functor instance. A couple of great examples of this are the list type and the Maybe type; fmap of a function into a list context is exactly the same as the familiar map operation on lists, and fmap of a function into a Maybe context will apply the function normally for a Just a value and do nothing for a Nothing value, allowing you to perform operations on it without worrying about which it is.
Having said all that, by a quirk of history the Haskell Prelude doesn't currently require Monad instances to also have a Functor instance, so Monad provides a family of functions that also lift operations into monadic contexts. The operation liftM does the same thing that fmap does for Monad instances that are also Functor instances (as they should be). But fmap and liftM only lift single-argument functions. Monad helpfully provides a family of liftM2 -- liftM5 functions that lift multi-argument functions into monadic context in the same way.
Finally, you asked about liftIO, which brings in the related idea of monad transformers, in which multiple Monad instances are combined in a single data type by applying monad mappings to already-monadic values, forming a kind of stack of monadic mappings over a basic pure type. The mtl library provides one implementation of this general idea, and in its module Control.Monad.Trans it defines two classes, MonadTrans t and Monad m => MonadIO m. The MonadTrans class provides a single function, lift, that gives access to operations in the next higher monadic "layer" in the stack, i.e. (MonadTrans t, Monad m) => m a -> t m a. The MonadIO class provides a single function, liftIO, that provides access to IO monad operations from any "layer" in the stack, i.e. IO a -> m a. These make working with monad transformer stacks much more convenient at the cost of having to provide a lot of transformer instance declarations when new Monad instances are introduced to a stack.