I try to understand the lifting principle by example, and found this:
https://github.com/graninas/Functional-Design-and-Architecture/blob/1736abc16d3e4917fc466010dcc182746af2fd0e/First-Edition/BookSamples/CH03/MonadStack.hs
Then, if I change it's lift (lift (putStrLn "bla-bla")) to putStrLn "bla-bla", the compiler throw error!
I do this base on my understanding: do block are just syntax sugar, and each line's result are pass into next line. If the next line do not use the args that passed from previous line, the type of args won't cause type confliction, I think.
Take bellow as example, while x<- getLine can past compiling
test:: IO ()
test = do
x <- getLine -- discarded and compiler don't care it type
let a = "bla-bla" -- discarded and compiler don't care it type
putStrLn $ "You type are discarded: "
Now back to the calculations function:
type Data = Map.Map Int String
type StateIO = StateT Data IO
type MaybeStateIO a = MaybeT StateIO a
calculations :: MaybeStateIO ()
calculations = do
lift (lift (putStrLn "bla-bla")) -- if I change this to `putStrLn "bla-bla"`, it failed compiling.
lift (modify (Map.insert 3 "3"))
lift (modify (Map.insert 1 "1"))
mb <- lift (get >>= (return . Map.lookup 1))
lift (lift (print mb))
main = runStateT (runMaybeT calculations) Map.empty
I don't understand is that to compiler require lifting on putStrLn "bla-bla".
Isn't it enough when return value of the last line of do block match the function's return value?
In this example, how does the compiler decide the do block's value type? according to function's signature?
Can anyone explains the lift for me? How do it work, when to use, etc.
Isn't it enough when return value of the last line of do block match the function's return value?
No, since that would mean that you could write a do block where the first item for example would use the instance of [] for Monad whereas the next would use for example Maybe or IO, but then how would x <- some_list make sense for a list of putStrLn x? All lines in the do block should be of type m a with m the same instance of Monad, and the as can have different types for each line. If you write a do block with:
foo = do
x <- exp1
exp2
then this is translated to exp1 >>= \x -> exp2, and since (>>=) :: Monad m => m a -> (a -> m b) -> m b operates where the two operands share the same monad m, this thus means that exp1 :: m a and exp2 :: m b thus need to work with the same monadic type m.
You require to perform lifting twice since the line should have as type MaybeT (StateT Data IO) a whereas putStrLn "bla-bla" has IO a, it thus requires one lift :: (MonadTrans t, Monad m) => m a -> t m a to lift it to StateT Data IO a and another to finally lift it to a MaybeT (StateT Data IO) a.
The value of calculations is a MaybeStateIO value. That's the monad you are operating in, so that's what every line of the do block has to produce. But putStrLn "bla-bla" does not produce a MaybeStateIO value; it just produces an IO value. The first lift takes that IO value and returns a StateIO value; the second lift takes that StateIO value and returns a MaybeStateIO value.
Remember,
do
a
b
is just syntactic sugar for a >> b, and (>>) :: Monad m => m a -> m b -> m b needs values from the same monad as arguments. It's only the "return value" (a and b) of the monad that can vary from line to line; the monad m itself is fixed.
Related
I'm trying so hard to wrap my head around the State Monad, and I do not understand the following:
Given the implementation of return and (>>=), when you say State $ \s ->...., where does s come from? I mean, when you start performing >>= ... >>=, doesn't it mean that somewhere in your beginning of the chain you somehow have to provide for that initial parameter?
newtype State s a=State { runState::s->(a,s) }
instance Monad (State s) where
return a=State $ \s->(a,s)
(>>=) m g=State $ \s -> let (a,s')= runState m s in
runState (g a) s'
In (>>=) you say State $ \s -> runState m s, and I do not get when is that initial (\s -> ...) argument (with a REAL argument) called?
Can someone explain, please?
Later Edit:
Can someone show me how would the initial state be set, let's say if it needs to get a value using getLine?
main::IO()
main=do
argument<-getLine
--how do i set initial state with argument?
m >> f1 >> f2 >> f3
when you say State $ \s ->...., where does s come from ?
It will come from the invocation, when runState will supply the initial state value to the state-monadic value, to run the combined computation it describes:
st = do { x <- get ; return (x+1) }
x = runState st 0 -- x is (1,0)
I also sense another possible misunderstanding on your part: you write: "when is that initial (\s -> ...) argument called?" There's no "initial" lambda: the lambdas are all nested inside!
do { a <- as; b <- bs; c <- foo b; return c }
translates as
as >>= (\a -> bs >>= (\b -> foo b >>= (\c -> return c)))
so it's not "initial", that's one combined all-enclosing lambda that is called with the initial state!
And then it will call
let (a,s1) = runState as s0
etc. with that "initial" as in the do block.
the do block does not perform any stateful computation - it only assembles some smaller stateful computations into one bigger stateful computation. At the do level, the actual state does not exist.
It would be simpler and maybe even more accurate if the monad was called "a stateful computation". Or "a function that takes state of type S and returns another state of the same type alongside its actual result". Then you could imagine >>= as "combines two functions of the aforementioned type into one, such that the state returned by the first one is be passed as a parameter to the second one".
State is just a wrapper around functions of type s -> (a, s). runState doesn't actually "run" anything; it just gives back the function wrapped by the State constructor. You can, however, compare runState to the ($) operator for functions.
($) f x = f x
runState (State f) s = f s
That makes (=<<) = flip (>>=) similar to (<<<) = (.); just rather than taking two functions and returning a third function, it takes a function (that returns a State) and a State and produces a second State.
However, we'll make a direct comparison of (>>=) to (>>>) = flip (.) so that the types align better. (Similarly, you could compare (.) to (=<<).)
-- f :: t -> a
-- g :: a -> b
f >>> g = \t -> let a = ($) f t
in ($) g a
-- m :: State s a
-- g :: a -> State s b
m >>= g = State $ \s -> let (a, s') = runState m s
in runState (g a) s'
Somewhat mystified by the following code. In non-toy version of the problem I'm trying to do a monadic computation in a monad Result, the values of which can only be constructed from within IO. Seems like the magic behind IO makes such computations strict, but I can't figure out how exactly that happens.
The code:
data Result a = Result a | Failure deriving (Show)
instance Functor Result where
fmap f (Result a) = Result (f a)
fmap f Failure = Failure
instance Applicative Result where
pure = return
(<*>) = ap
instance Monad Result where
return = Result
Result a >>= f = f a
Failure >>= _ = Failure
compute :: Int -> Result Int
compute 3 = Failure
compute x = traceShow x $ Result x
compute2 :: Monad m => Int -> m (Result Int)
compute2 3 = return Failure
compute2 x = traceShow x $ return $ Result x
compute3 :: Monad m => Int -> m (Result Int)
compute3 = return . compute
main :: IO ()
main = do
let results = mapM compute [1..5]
print $ results
results2 <- mapM compute2 [1..5]
print $ sequence results2
results3 <- mapM compute3 [1..5]
print $ sequence results3
let results2' = runIdentity $ mapM compute2 [1..5]
print $ sequence results2'
The output:
1
2
Failure
1
2
4
5
Failure
1
2
Failure
1
2
Failure
Nice test cases. Here's what's happening:
in mapM compute we see laziness at work, as usual. No surprise here.
in mapM compute2 we work inside the IO monad, whose mapM definition will demand the whole list: unlike Result which skips the tail of the list as soon as Failure is found, IO will always scan the whole list. Note the code:
compute2 x = traceShow x $ return $ Result x
So, the above wil print the debug message as soon as each element of the list of IO actions is accessed. All are, so we print everything.
in mapM compute3 we now use, roughly:
compute3 x = return $ traceShow x $ Result x
Now, since return in IO is lazy, it will not trigger the traceShow when returning the IO action. So, when mapM compute3 is run, no message is seen. Instead, we see messages only when sequence results3 is run, which forces the Result -- not all of them, but only as much as needed.
the final Identity example is also quite tricky. Note this:
> newtype Id1 a = Id1 a
> data Id2 a = Id2 a
> Id1 (trace "hey!" True) `seq` 42
hey!
42
> Id2 (trace "hey!" True) `seq` 42
42
when using a newtype, at runtime there is no boxing/unboxing (AKA lifting) involved, so forcing a Id1 x value causes x to be forced. With data types this does not happen: the value is wrapped in a box (e.g. Id2 undefined is not equivalent to undefined).
In your example, you add an Identity constructor, but that is from the newtype Identity!! So, when calling
return $ traceShow x $ Result x
the return here does not wrap anything, and the traceShow is immediately triggered as soon as mapM is run.
Your Result type appears to be virtually identical to Maybe, with
Result <-> Just
Failure <-> Nothing
For the sake of my poor brain, I'll stick to Maybe terminology in the rest of this answer.
chi explained why IO (Maybe a) does not short-circuit the way you expected. But there is a type you can use for this sort of thing! It's essentially the same type, in fact, but with a different Monad instance. You can find it in Control.Monad.Trans.Maybe. It looks something like this:
newtype MaybeT m a = MaybeT
{ runMaybeT :: m (Maybe a) }
As you can see, this is just a newtype wrapper around m (Maybe a). But its Monad instance is very different:
instance Monad m => Monad (MaybeT m) where
return a = MaybeT $ return (Just a)
m >>= f = MaybeT $ do
mres <- runMaybeT m
case mres of
Nothing -> return Nothing
Just a -> runMaybeT (f a)
That is, m >>= f runs the m computation in the underlying monad, getting Maybe something or other. If it gets Nothing, it just stops, returning Nothing. If it gets something, it passes that to f and runs the result. You can also turn any m action into a "successful" MaybeT m action using lift from Control.Monad.Trans.Class:
class MonadTrans t where
lift :: Monad m => m a -> t m a
instance MonadTrans MaybeT where
lift m = MaybeT $ Just <$> m
You can also use this class, defined somewhere like Control.Monad.IO.Class, which is often clearer and can be much more convenient:
class MonadIO m where
liftIO :: IO a -> m a
instance MonadIO IO where
liftIO m = m
instance MonadIO m => MonadIO (MaybeT m) where
liftIO m = lift (liftIO m)
I want to sequentially compose two monad actions in Haskell, discarding any value produced by the second, and passing the argument to both actions. Currently I'm using a do-block like this:
ask = do
result <- getLine
putStrLn result
return result
I was hoping to write this a little more point free and neat, so I tried this:
ask' = getLine <* putStrLn
However, this doesn't even type check and the problem is that <* does not transfer the result of the first action to the second. I want to chain the actions like >>= does, but not change the result. The type should be (a -> m b) -> (a -> m c) -> (a -> m b), but Hoogle yields no suitable results. What would be an operator to achieve this function composition?
As a tendency, if you use one value in two different places it probably is a good idea to give it a name in a clear do block, rather than pressing on pointless style.
The abstract concept of splitting up information flow to different actions is captured by cartesian monoidal categories, known to Haskellers as arrows. In your case, you're basically working in the IO Kleisli category:
import Prelude hiding (id)
import Control.Arrow
ask' :: Kleisli IO () String
ask' = Kleisli (\()->getLine) >>> (putStrLn &&& id) >>> arr snd
I don't think it's a good idea to write such code.
I want to sequentially compose two monad actions in Haskell, discarding any value produced by the second, and passing the argument to both actions.
This sounds to me like a Reader—the function type r -> m a is isomorphic to ReaderT r m a, and the monad works by implicitly plugging in the same r value into all the "holes." So for example:
import Control.Applicative
import Control.Monad.Reader
example :: IO String
example = getLine >>= discarding putStrLn
discarding :: Monad m => (a -> m b) -> a -> m a
discarding action = runReaderT (ReaderT action *> ask)
The operator you want is then something like:
action `thingy` extra = action >>= discarding extra
But of course discarding has a simpler implementation:
discarding :: Applicative f => (a -> f b) -> a -> f a
discarding action a = action a *> return a
...so in the end I think this is really code golf. But in a more complex program where this is a common pattern at a larger scale it might be worth a shot. Basically, if you have:
a0 :: r -> m a0
a1 :: r -> m a1
.
.
.
an :: r -> m an
Then it follows that:
ReaderT a0 :: ReaderT r m a0
ReaderT a1 :: ReaderT r m a1
.
.
.
ReaderT an :: ReaderT r m an
And then:
runReaderT (ReaderT a0 <* ReaderT a1 <* ... <* ReaderT an) :: r -> m a0
For completeness, in this particular case (the IO) monad, you could also abuse bracket for this purpose:
bracket getLine putStrLn return
But I strongly discourage it, as this will be much less readable than the original do-notation block, it's just ugly.
As already mentioned, in this particular case naming the result seems the best way.
See also Should do-notation be avoided in Haskell?
I was playing around with composable failures and managed to write a function with the signature
getPerson :: IO (Maybe Person)
where a Person is:
data Person = Person String Int deriving Show
It works and I've written it in the do-notation as follows:
import Control.Applicative
getPerson = do
name <- getLine -- step 1
age <- getInt -- step 2
return $ Just Person <*> Just name <*> age
where
getInt :: IO (Maybe Int)
getInt = do
n <- fmap reads getLine :: IO [(Int,String)]
case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
I wrote this function with the intent of creating composable possible failures. Although I've little experience with monads other than Maybe and IO this seems like if I had a more complicated data type with many more fields, chaining computations wouldn't be complicated.
My question is how would I rewrite this without do-notation? Since I can't bind values to names like name or age I'm not really sure where to start.
The reason for asking is simply to improve my understanding of (>>=) and (<*>) and composing failures and successes (not to riddle my code with illegible one-liners).
Edit: I think I should clarify, "how should I rewrite getPerson without do-notation", I don't care about the getInt function half as much.
Do-notation desugars to (>>=) syntax in this manner:
getPerson = do
name <- getLine -- step 1
age <- getInt -- step 2
return $ Just Person <*> Just name <*> age
getPerson2 =
getLine >>=
( \name -> getInt >>=
( \age -> return $ Just Person <*> Just name <*> age ))
each line in do-notation, after the first, is translated into a lambda which is then bound to the previous line. It's a completely mechanical process to bind values to names. I don't see how using do-notation or not would affect composability at all; it's strictly a matter of syntax.
Your other function is similar:
getInt :: IO (Maybe Int)
getInt = do
n <- fmap reads getLine :: IO [(Int,String)]
case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
getInt2 :: IO (Maybe Int)
getInt2 =
(fmap reads getLine :: IO [(Int,String)]) >>=
\n -> case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
A few pointers for the direction you seem to be headed:
When using Control.Applicative, it's often useful to use <$> to lift pure functions into the monad. There's a good opportunity for this in the last line:
Just Person <*> Just name <*> age
becomes
Person <$> Just name <*> age
Also, you should look into monad transformers. The mtl package is most widespread because it comes with the Haskell Platform, but there are other options. Monad transformers allow you to create a new monad with combined behavior of the underlying monads. In this case, you're using functions with the type IO (Maybe a). The mtl (actually a base library, transformers) defines
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
This is the same as the type you're using, with the m variable instantiated at IO. This means you can write:
getPerson3 :: MaybeT IO Person
getPerson3 = Person <$> lift getLine <*> getInt3
getInt3 :: MaybeT IO Int
getInt3 = MaybeT $ do
n <- fmap reads getLine :: IO [(Int,String)]
case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
getInt3 is exactly the same except for the MaybeT constructor. Basically, any time you have an m (Maybe a) you can wrap it in MaybeT to create a MaybeT m a. This gains simpler composability, as you can see by the new definition of getPerson3. That function doesn't worry about failure at all because it's all handled by the MaybeT plumbing. The one remaining piece is getLine, which is just an IO String. This is lifted into the MaybeT monad by the function lift.
Edit
newacct's comment suggests that I should provide a pattern matching example as well; it's basically the same with one important exception. Consider this example (the list monad is the monad we're interested in, Maybe is just there for pattern matching):
f :: Num b => [Maybe b] -> [b]
f x = do
Just n <- x
[n+1]
-- first attempt at desugaring f
g :: Num b => [Maybe b] -> [b]
g x = x >>= \(Just n) -> [n+1]
Here g does exactly the same thing as f, but what if the pattern match fails?
Prelude> f [Nothing]
[]
Prelude> g [Nothing]
*** Exception: <interactive>:1:17-34: Non-exhaustive patterns in lambda
What's going on? This particular case is the reason for one of the biggest warts (IMO) in Haskell, the Monad class's fail method. In do-notation, when a pattern match fails fail is called. An actual translation would be closer to:
g' :: Num b => [Maybe b] -> [b]
g' x = x >>= \x' -> case x' of
Just n -> [n+1]
_ -> fail "pattern match exception"
now we have
Prelude> g' [Nothing]
[]
fails usefulness depends on the monad. For lists, it's incredibly useful, basically making pattern matching work in list comprehensions. It's also very good in the Maybe monad, since a pattern match error would lead to a failed computation, which is exactly when Maybe should be Nothing. For IO, perhaps not so much, as it simply throws a user error exception via error.
That's the full story.
do-blocks of the form var <- e1; e2 desugar to expressions using >>= as follows e1 >>= \var -> e2. So your getPerson code becomes:
getPerson =
getLine >>= \name ->
getInt >>= \age ->
return $ Just Person <*> Just name <*> age
As you see this is not very different from the code using do.
Actually, according to this explaination, the exact translation of your code is
getPerson =
let f1 name =
let f2 age = return $ Just Person <*> Just name <*> age
f2 _ = fail "Invalid age"
in getInt >>= f2
f1 _ = fail "Invalid name"
in getLine >>= f1
getInt =
let f1 n = case n of
((x,""):[]) -> return (Just x)
_ -> return Nothing
f1 _ = fail "Invalid n"
in (fmap reads getLine :: IO [(Int,String)]) >>= f1
And the pattern match example
f x = do
Just n <- x
[n+1]
translated to
f x =
let f1 Just n = [n+1]
f1 _ = fail "Not Just n"
in x >>= f1
Obviously, this translated result is less readable than the lambda version, but it works with or without pattern matching.
Particularly, I need to be able to combine the CGI monad with the IO monad, but an example of how to combine the IO monad with the Maybe monad might be even better...
I assume you want to use the Maybe monad for early termination (like break or return in C).
In that case you should use MaybeT from the MaybeT package (cabal install MaybeT).
main = do
runMaybeT . forever $ do
liftIO $ putStrLn "I won't stop until you type pretty please"
line <- liftIO getLine
when ("pretty please" == line) mzero
return ()
MaybeT is a monad transformer version of the maybe monad.
Monad transformers "add functionality" to other monads.
You don't exactly say how you want to combine IO and Maybe, but I assume you have many functions that return IO (Maybe a) that you want to combine easily. Basically you want to treat IO (Maybe a) as a separate type with it's own Monad instance:
newtype IOMaybe a = IOM (IO (Maybe a))
-- "unpack" a value of the new type
runIOMaybe :: IOMaybe a -> IO (Maybe a)
runIOMaybe (IOM a) = a
instance Monad IOMaybe where
-- bind operator
(IOM ioa) >>= f = IOM $ do
a <- ioa
case a of
Nothing -> return Nothing
Just v -> runIOMaybe (f v)
-- return
return a = IOM (return (Just a))
-- maybe also some convenience functions
returnIO :: IO a -> IOMaybe a
returnIO ioa = IOM $ do
v <- ioa
return (Just v)
returnMaybe :: Maybe a -> IOMaybe a
returnMaybe ma = IOM (return ma)
With this you can use the do-Notation to combine functions that return IO (Maybe a), IO a or Maybe a:
f1 :: Int -> IO (Maybe Int)
f1 0 = return Nothing
f1 a = return (Just a)
main = runIOMaybe $ do
returnIO $ putStrLn "Hello"
a <- returnMaybe $ Just 2
IOM $ f1 a
return ()
Generally something that combines and modifies monads like this is called a monad transformer, and GHC comes with a package that includes monad transformers for common cases. If there is something in this monad transformer library that fits your scenario depends on how exactly you want to combine Maybe and IO.
In what sense do you want to combine the monads?
f :: Int -> IO (Maybe Int)
f x = do
putStrLn "Hello world!"
return $ if x == 0 then Nothing else Just x
Can be evaluated to:
[1 of 1] Compiling Main ( maybe-io.hs, interpreted )
Ok, modules loaded: Main.
*Main> f 0
Hello world!
Nothing
*Main> f 3
Hello world!
Just 3