The do notation allows us to express monadic code without overwhelming nestings, so that
main = getLine >>= \ a ->
getLine >>= \ b ->
putStrLn (a ++ b)
can be expressed as
main = do
a <- getLine
b <- getLine
putStrLn (a ++ b)
Suppose, though, the syntax allows ... #expression ... to stand for do { x <- expression; return (... x ...) }. For example, foo = f a #(b 1) c would be desugared as: foo = do { x <- b 1; return (f a x c) }. The code above could, then, be expressed as:
main = let a = #getLine in
let b = #getLine in
putStrLn (a ++ b)
Which would be desugared as:
main = do
x <- getLine
let a = x in
return (do
x' <- getLine
let b = x' in
return (putStrLn (a ++ b)))
That is equivalent. This syntax is appealing to me because it seems to offer the same functionality as the do-notation, while also allowing some shorter expressions such as:
main = putStrLn (#(getLine) ++ #(getLine))
So, I wonder if there is anything defective with this proposed syntax, or if it is indeed complete and equivalent to the do-notation.
putStrLn is already String -> IO (), so your desugaring ... return (... return (putStrLn (a ++ b))) ends up having type IO (IO (IO ())), which is likely not what you wanted: running this program won't print anything!
Speaking more generally, your notation can't express any do-block which doesn't end in return. [See Derek Elkins' comment.]
I don't believe your notation can express join, which can be expressed with do without any additional functions:
join :: Monad m => m (m a) -> m a
join mx = do { x <- mx; x }
However, you can express fmap constrained to Monad:
fmap' :: Monad m => (a -> b) -> m a -> m b
fmap' f mx = f #mx
and >>= (and thus everything else) can be expressed using fmap' and join. So adding join would make your notation complete, but still not convenient in many cases, because you end up needing a lot of joins.
However, if you drop return from the translation, you get something quite similar to Idris' bang notation:
In many cases, using do-notation can make programs unnecessarily verbose, particularly in cases such as m_add above where the value bound is used once, immediately. In these cases, we can use a shorthand version, as follows:
m_add : Maybe Int -> Maybe Int -> Maybe Int
m_add x y = pure (!x + !y)
The notation !expr means that the expression expr should be evaluated and then implicitly bound. Conceptually, we can think of ! as being a prefix function with the following type:
(!) : m a -> a
Note, however, that it is not really a function, merely syntax! In practice, a subexpression !expr will lift expr as high as possible within its current scope, bind it to a fresh name x, and replace !expr with x. Expressions are lifted depth first, left to right. In practice, !-notation allows us to program in a more direct style, while still giving a notational clue as to which expressions are monadic.
For example, the expression:
let y = 42 in f !(g !(print y) !x)
is lifted to:
let y = 42 in do y' <- print y
x' <- x
g' <- g y' x'
f g'
Adding it to GHC was discussed, but rejected (so far). Unfortunately, I can't find the threads discussing it.
How about this:
do a <- something
b <- somethingElse a
somethingFinal a b
Related
I'm learning do expression and Monad using LEARN YOU A HASKELL FOR GREAT GOOD. There's a gcd implementation using tell function makes me confused.
gcd :: Int -> Int -> Writer [String] Int
gcd a b
| b == 0 = tell ["Finished with " ++ show a ] >>= (\_ -> return a)
| otherwise = tell [show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b)] >>= (\_ -> gcd b (a `mod` b))
gcdResult = gcd 8 3
-- result: WriterT (Identity (1,["8 mod 3 = 2","3 mod 2 = 1","2 mod 1 = 0","Finished with 1"]))
But I am confused by the tell function. When using >>= (\_ -> ...) or >>, the result before will be ignored, so why does the result of tell can be passed to the final result? As my thought, the tell result may be ignored, and the final result will be WriterT (Identity (1,[])).
You're confusing the result with the context. You are correct that, when applying >> or >>= \_ ->, the result of the left-hand-side is ignored. However, if the entire value was ignored, it would be completely pointless; the monadic context can be passed forward.
a >> b
This means "take the context from a and combine it with the context of b, keeping the result value of b". In the case of Writer, the monadic context is that there is some write-only data being passed about.
tell :: Monoid w => w -> Writer w ()
This is the (somewhat simplified) type of tell. It takes a value to write and returns a Writer instance whose result value is insignificant (()) but whose context is that there is a write-only value containing the w argument. When you apply >>, the result value is ignored (which is irrelevant because tell returns nothing of value through its result) but the context is kept.
I have this Haskell code which when compiled with GHC and run, aborts with a loop detected.
data Foo = Foo ()
deriving (Eq,Show)
type Foop = Foo -> ((),Foo)
noOp :: Foop
noOp st = ((),st)
someOp :: Foop
someOp st#(Foo x) = ((),st)
(<+>) :: Foop -> Foop -> Foop
(<+>) f g st = let ((_,st'),(_,st'')) = ((f st),(g st')) in ((),st'')
main = print $ (noOp <+> someOp) $ Foo ()
I think it shouldn't, and here are some modifications. Each of them makes the loop go away:
change data Foo to newtype Foo
change (noOp <+> someOp) to (someOp <+> noOp)
remove the deconstruction #(Foo x)
Is this a bug in GHC or is it my lack of understanding the evaluation process?
Pattern match (_, _) demands WHNF of (f st, g st'). Easy.
Pattern match (_, (_,_)) demands WHNF of g st'. Here's the problem, because g is strict, hence it first needs st' in WHNF too. The runtime finds st' in the pattern ((_,st'), (_,_)), so before it can actually traverse down into st' it needs to WHNF both of the tuples. Because g is strict however, this first requires st'... and so on.
If you match the result of g with a lazy irrefutable pattern
(<+>) f g st = let ((_,st'), ~(_,st'')) = (f st, g st') in ((),st'')
then the problem goes away, because this is evaluated thus:
Pattern match (_, _) demands WHNF of (f st, g st'). Easy.
Pattern match (_, ~(_,_)) demands nothing more for the time being.
Pattern match ((_,st'), ~(_,_)) demands WHNF of f st. Fortunately, we can fulfill this, because st does not depend on the pattern.
Now we've satisfied the pattern match, the runtime can already proceed with the in ((),st''). Only at this point is the irrefutable pattern ~(_,st'') forced, but this is now not a problem anymore because st' is available here, so it's just a matter of computing g once.
The fixes you've tried all amount to making g non-strict:
remove the deconstruction #(Foo _)
Without that, g doesn't really need to look at its argument to construct the result skeleton, i.e. the tuple match (_,st'') can then succeed without first requiring WHNF of st'.
change data Foo to newtype Foo
This has the effect that the Foo constructor doesn't actually exist at runtime, so there's nothing that the pattern st#(Foo _) would force.
change noOp <+> someOp to someOp <+> noOp
As I said, the loop only comes about because g is strict. If you put f in its position, which is not strict, then there's no problem.
It's not a bug -- you just found a tricky corner of the lazy pattern semantics. Let me present a simpler case:
> data Id a = Id a
> let Id a = undefined ; Id b = Id 3 in b
3
> let (Id a, Id b) = (undefined, Id 3) in b
*** Exception: Prelude.undefined
The difference is that the first let is equivalent to
case undefined of
~(Id a) -> case Id 3 of
~(Id b) -> b
while the second is
case (undefined, Id 3) of
~(Id a, Id b) -> b
The first will not evaluate the undefined unless a is demanded (which does not happen).
The second will pattern match against both patterns Id a and Id b as soon as either variable is demanded, forcing both undefined and Id 3 in the process.
Note that, because of this issue, the patterns ~(K1 (K2 x) (K3 y)), ~(K1 ~(K2 x) (K3 y)), ~(K1 (K2 x) ~(K3 y)) and ~(K1 ~(K2 x) ~(K3 y)) have different semantics.
To fix your code, try
let (~(_,st'),~(_,st'')) = ((f st),(g st')) in ((),st'')
or
let (_,st') = f st ; (_,st'') = g st' in ((),st'')
I am working with Haskell and maybe monads but I am a little bit confused with them
here is my code but I am getting error and I do not know how to improve my code.
doAdd :: Int -> Int -> Maybe Int
doAdd x y = do
result <- x + y
return result
Let's look critically at the type of the function that you're writing:
doAdd :: Int -> Int -> Maybe Int
The point of the Maybe monad is to work with types that are wrapped with a Maybe type constructor. In your case, the two Int arguments are just plain Ints, and the + function always produces an Int so there is no need for the monad.
If instead, your function took Maybe Int as its arguments, then you could use do notation to handle the Nothing case behind the scenes:
doAdd :: Maybe Int -> Maybe Int -> Maybe Int
doAdd mx my = do x <- mx
y <- my
return (x + y)
example1 = doAdd (Just 1) (Just 3) -- => Just 4
example2 = doAdd (Just 1) Nothing -- => Nothing
example3 = doAdd Nothing (Just 3) -- => Nothing
example4 = doAdd Nothing Nothing -- => Nothing
But we can extract a pattern from this: what you are doing, more generically, is taking a function ((+) :: Int -> Int -> Int) and adapting it to work in the case where the arguments it wants are "inside" a monad. We can abstract away from the specific function (+) and the specific monad (Maybe) and get this generic function:
liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
liftM2 f ma mb = do a <- ma
b <- mb
return (f a b)
Now with liftM2 you can write:
doAdd :: Maybe Int -> Maybe Int -> Maybe Int
doAdd = liftM2 (+)
The reason why I chose the name liftM2 is because this is actually a library function—you don't need to write it, you can import the Control.Monad module and you'll get it for free.
What would be a better example of using the Maybe monad? When you have an operation that, unlike +, can intrinsically can produce a Maybe result. One idea would be if you wanted to catch division by 0 mistakes. You could write a "safe" version of the div function:
-- | Returns `Nothing` if second argument is zero.
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)
Now in this case the monad does become more useful:
-- | This function tests whether `x` is divisible by `y`. Returns `Nothing` if
-- division by zero.
divisibleBy :: Int -> Int -> Maybe Bool
divisibleBy x y = do z <- safeDiv x y
let x' = z * y
return (x == x')
Another more interesting monad example is if you have operations that return more than one value—for example, positive and negative square roots:
-- Compute both square roots of x.
allSqrt x = [sqrt x, -(sqrt x)]
-- Example: add the square roots of 5 to those of 7.
example = do x <- allSqrt 5
y <- allSqrt 7
return (x + y)
Or using liftM2 from above:
example = liftM2 (+) (allSqrt 5) (allSqrt 7)
So anyway, a good rule of thumb is this: never "pollute" a function with a monad type if it doesn't really need it. Your original doAdd—and even my rewritten version—are a violation of this rule of thumb, because what the function does is adding, but adding has nothing to do with Maybe—the Nothing handling is just a behavior that we add on top of the core function (+). The reason for this rule of thumb is that any function that does not use monads can be generically adapted to add the behavior of any monad you want, using utility functions like liftM2 (and many other similar utility functions).
On the other hand, safeDiv and allSqrt are examples where you can't really write the function you want without using Maybe or []; if you are dealing with a function like that, then monads are often a convenient abstraction for eliminating boilerplate code.
A better example might be
justPositive :: Num a => a -> Maybe a
justPositive x
| x <= 0 = Nothing
| otherwise = Just x
addPositives x y = do
x' <- justPositive x
y' <- justPositive y
return $ x' + y'
This will filter out any non-positive values passed into the function using do notation
That isn't how you'd write that code. The <- operator is for getting a value out of a monad. The result of x + y is just a number, not a monad wrapping a number.
Do notation is actually completely wasteful here. If you were bound and determined to write it that way, it would have to look like this:
doAdd x y = do
let result = x + y
return result
But that's just a longwinded version of this:
doAdd x y = return $ x + y
Which is in turn equivalent to
doAdd x y = Just $ x + y
Which is how you'd actually write something like this.
The use case you give doesn't justify do notation, but this is a more common use case- You can chain functions of this type together.
func::Int->Int->Maybe Int -- func would be a function like divide, which is undefined for division by zero
main = do
result1 <- func 1 2
result2 <- func 3 4
result3 <- func result1 result2
return result3
This is the whole point of monads anyway, chaining together functions of type a->m a.
When used this way, the Maybe monad acts much like exceptions in Java (you can use Either if you want to propagate a message up).
How do you increment a variable in a functional programming language?
For example, I want to do:
main :: IO ()
main = do
let i = 0
i = i + 1
print i
Expected output:
1
Simple way is to introduce shadowing of a variable name:
main :: IO () -- another way, simpler, specific to monads:
main = do main = do
let i = 0 let i = 0
let j = i i <- return (i+1)
let i = j+1 print i
print i -- because monadic bind is non-recursive
Prints 1.
Just writing let i = i+1 doesn't work because let in Haskell makes recursive definitions — it is actually Scheme's letrec. The i in the right-hand side of let i = i+1 refers to the i in its left hand side — not to the upper level i as might be intended. So we break that equation up by introducing another variable, j.
Another, simpler way is to use monadic bind, <- in the do-notation. This is possible because monadic bind is not recursive.
In both cases we introduce new variable under the same name, thus "shadowing" the old entity, i.e. making it no longer accessible.
How to "think functional"
One thing to understand here is that functional programming with pure — immutable — values (like we have in Haskell) forces us to make time explicit in our code.
In imperative setting time is implicit. We "change" our vars — but any change is sequential. We can never change what that var was a moment ago — only what it will be from now on.
In pure functional programming this is just made explicit. One of the simplest forms this can take is with using lists of values as records of sequential change in imperative programming. Even simpler is to use different variables altogether to represent different values of an entity at different points in time (cf. single assignment and static single assignment form, or SSA).
So instead of "changing" something that can't really be changed anyway, we make an augmented copy of it, and pass that around, using it in place of the old thing.
As a general rule, you don't (and you don't need to). However, in the interests of completeness.
import Data.IORef
main = do
i <- newIORef 0 -- new IORef i
modifyIORef i (+1) -- increase it by 1
readIORef i >>= print -- print it
However, any answer that says you need to use something like MVar, IORef, STRef etc. is wrong. There is a purely functional way to do this, which in this small rapidly written example doesn't really look very nice.
import Control.Monad.State
type Lens a b = ((a -> b -> a), (a -> b))
setL = fst
getL = snd
modifyL :: Lens a b -> a -> (b -> b) -> a
modifyL lens x f = setL lens x (f (getL lens x))
lensComp :: Lens b c -> Lens a b -> Lens a c
lensComp (set1, get1) (set2, get2) = -- Compose two lenses
(\s x -> set2 s (set1 (get2 s) x) -- Not needed here
, get1 . get2) -- But added for completeness
(+=) :: (Num b) => Lens a b -> Lens a b -> State a ()
x += y = do
s <- get
put (modifyL x s (+ (getL y s)))
swap :: Lens a b -> Lens a b -> State a ()
swap x y = do
s <- get
let x' = getL x s
let y' = getL y s
put (setL y (setL x s y') x')
nFibs :: Int -> Int
nFibs n = evalState (nFibs_ n) (0,1)
nFibs_ :: Int -> State (Int,Int) Int
nFibs_ 0 = fmap snd get -- The second Int is our result
nFibs_ n = do
x += y -- Add y to x
swap x y -- Swap them
nFibs_ (n-1) -- Repeat
where x = ((\(x,y) x' -> (x', y)), fst)
y = ((\(x,y) y' -> (x, y')), snd)
There are several solutions to translate imperative i=i+1 programming to functional programming. Recursive function solution is the recommended way in functional programming, creating a state is almost never what you want to do.
After a while you will learn that you can use [1..] if you need a index for example, but it takes a lot of time and practice to think functionally instead of imperatively.
Here's a other way to do something similar as i=i+1 not identical because there aren't any destructive updates. Note that the State monad example is just for illustration, you probably want [1..] instead:
module Count where
import Control.Monad.State
count :: Int -> Int
count c = c+1
count' :: State Int Int
count' = do
c <- get
put (c+1)
return (c+1)
main :: IO ()
main = do
-- purely functional, value-modifying (state-passing) way:
print $ count . count . count . count . count . count $ 0
-- purely functional, State Monad way
print $ (`evalState` 0) $ do {
count' ; count' ; count' ; count' ; count' ; count' }
Note: This is not an ideal answer but hey, sometimes it might be a little good to give anything at all.
A simple function to increase the variable would suffice.
For example:
incVal :: Integer -> Integer
incVal x = x + 1
main::IO()
main = do
let i = 1
print (incVal i)
Or even an anonymous function to do it.
A simple question:
given the definitions, (From Haskell SOE)
do x — el; el\ ...; en
=> el »= \x — do e2\ ...; en
and:
do let decllist; el\...; en
=> let decllist in do e2\ ...; en
it seems that these two constructs are the same:
do let x = e1
e2
and
do x <- e1
e2
both evaluate e1, bind it to e2, and then evaluate e2.
Yes?
Let's do a simple example in the Maybe monad:
foo = do
let x = Just 1
return x
and
bar = do
x <- Just 1
return x
Desugaring both, we get
foo = let x = Just 1 in return x -- do notation desugaring
= return (Just 1) -- let
= Just (Just 1) -- definition of return for the Maybe monad
bar = let ok x = return x in Just 1 >>= ok -- do notation desugaring
= let ok x = return x in ok 1 -- definition of >>= for the Maybe monad
= return 1 -- definiton of ok
= Just 1 -- definition of return for the Maybe monad
For reference, I am using the translation from section 3.14 of the Haskell 2010 Report.
No, they are not the same. For example,
do let x = getLine
print x
translates to
let x = getLine in print x
this is a type error, as x will have the type IO String. We're asking to print the computation itself, not its result.
do x <- getLine
print x
translates to
getLine >>= \x -> print x
Here x is bound as the result of the computation and its type is String, so this type checks.
In do-notation, let just binds values to names like it always does, while <- is used to perform monadic binding, which is binding a name to the result of a computation.
Assuming e1 is a computation of type Monad m => m a, then let x = e1 and x <- e1 mean somewhat different things.
In the let-version, when you use x within a do-expression, you are dealing with a value of type Monad m => m a.
In the other version, when you use x within a do expression, you are dealing with a value of type a (since do-notation implicitly handles mapping over the monad).
For example:
e :: IO Int
f :: Int -> Int
-- the following will result in a type error, since f operates on `Int`, not `IO Int`:
g = do let x = e
return $ f x
-- the following will work:
g' = do x <- e
return $ f x
No. x <- e1 translates to e1 >>= \x ->, an incomplete expression; the let expression is just a normal let. Or are you asking if let and (>>=) are the same thing? They very much aren't: (>>=) exposes the thing wrapped by a monad to a function, which must produce something wrapped in the monad. In other words, with x <- e1, e1's type must be IO a for some a, but with let x = e1 e1's type is just a; in both cases the type of x will be a.