What is the difference between forM and forM_ in haskell? - haskell

HLint suggests that I use forM_ rather than forM. Why? I see they have different type signatures but haven't found a good reason to use one over the other.
forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()

The forM_ function is more efficient because it does not save the results of the operations. That is all. (This only makes sense when working with monads because a pure function of type a -> () is not particularly useful.)

Ok,
forM is mapM with its arguments flipped.
forM_ is mapM_ with its arguments flipped.
Let's see in mapM and mapM_ :
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM mf xs takes a monadic function mf (having type Monad m => (a -> m b)) and applies it to each element in list xs; the result is a list inside a monad.
The difference between mapM and mapM_ is, that mapM returns a list of the results, while mapM_ returns an empty result. The result of each action in mapM_ is not stored.

To understand the difference between (A): forM xs f and (B): forM_ xs f, it might help to compare the difference between the following:
-- Equivalent to (A)
do
r1 <- f x1
r2 <- f x2
...
rn <- f xn
return [r1, r2, ..., rn]
-- Equivalent to (B)
do
_ <- f x1
_ <- f x2
...
_ <- f xn
return ()
The crucial difference being that forM_ ignores the results r1, ... rn and just returns an empty result via return (). Think of the underscore as meaning "don't care" ... forM_ doesn't care about the results. forM however, does care about the results and returns them in as a list via return [r1, r2, ... rn].
Example 1
The code below asks for your name three times and prints the results of the forM.
import Control.Monad (forM, forM_)
main = do
let askName i = do
putStrLn $ "What's your name (" ++ (show i) ++ ")"
name <- getLine
return name
results <- forM [1,2,3] askName
putStrLn $ "Results = " ++ show results
An example execution with forM:
What's your name? (1)
> James
What's your name? (2)
> Susan
What's your name? (3)
> Alex
Results = ["James", "Susan", "Alex"]
But if we change the forM to a forM_, then we would have instead:
What's your name? (1)
> James
What's your name? (2)
> Susan
What's your name? (3)
> Alex
Results = ()
In your case, the linter is telling you that you're not using the return values of your forM (you don't have foo <- forM xs f, you probably have forM xs f by itself on a line) and so should use forM_ instead. This happens, for
example, when you are using a monadic action like putStrLn.
Example 2 The code below asks for your name and then says "Hello" – repeating three times.
import Control.Monad (forM, forM_)
main = do
let askThenGreet i = do
putStrLn $ "What's your name (" ++ (show i) ++ ")"
name <- getLine
putStrLn $ "Hello! " ++ name
forM [1,2,3] askThenGreet
An example execution with forM:
What's your name? (1)
> Sarah
Hello! Sarah
What's your name? (2)
> Dick
Hello! Dick
What's your name? (3)
> Peter
Hello! Peter
[(), (), ()]
The overall result of main comes from the result of the forM: [(), (), ()]. It's pretty useless and annoyingly, it appears in the console. But if we change the forM to a forM_, then we would have instead:
What's your name? (1)
> Sarah
Hello! Sarah
What's your name? (2)
> Dick
Hello! Dick
What's your name? (3)
> Peter
Hello! Peter
With that change, the overall result comes from the mapM_ and is now (). This doesn't show up in the console (a quirk of the IO monad)! Great!
Also, by using mapM_ here, it's clearer to other readers of your code – you're indirectly explaining / self-documenting that you don't care about the results [r1, ..., rn] = [(), (), ()] – and rightly so as they're useless here.

Related

Haskell mapM_ does not print

So I wrote a program to query a forex API (foreign exchange), and it works like a charm, but when I want to query every currency pair available, it evaluates all API calls as it takes a long time to execute but prints nothing.
import Data.Functor ((<&>))
supportedPairs :: IO (Maybe [(String, String)])
forex :: String -> String -> IO (Maybe (Scientific, UnixTime))
main :: IO ()
main = do
x <- supportedPairs
mapM_ (flip (<&>) print . uncurry forex) (fromJust x)
-- this prints nothing at all
The single calls work just fine like this:
main = do
x <- supportedPairs
u <- (uncurry forex . (flip (!!) 10 . fromJust)) x
print u
-- this prints "Just (438.685041,UnixTime {utSeconds = 1649588583, utMicroSeconds = 0})"
Why doesn't the mapM_ print the results although they are evaluated? If I understood Haskell's laziness correctly, then if the results are not to be printed they should not be evaluated in the first place?
Check the types:
print is ... -> IO ().
Therefore, ... <&> print is IO (IO ()). Note the double IO here.
Hence, mapping over that, will run the "outermost IO" but not the "innermost IO". More concretely, compare this:
main = do
x <- print True >> return 5 -- x is 5
y <- return (print True >> return 5) -- y is an IO action
...
Only the first print True here is executed: the second IO action is used to define y but until we run y it won't be executed.
The final point: here, you do not need <&> since that creates the nested IO's. Use flip (>>=) print (or (=<<) print, or (>>= print)) instead of flip <&> print.

How to get this function to be evaluated lazily

I have the following function:
main = do xs <- getContents
edLines <- ed $ lines xs
putStr $ unlines edLines
Firstly I used the working version main = interact (unlines . ed . lines) but changed the signature of ed since. Now it returns IO [String] instead of just [String] so I can't use this convenient definition any more.
The problem is that now my function ed is still getting evaluated partly but nothing is displayed till I close the stdin via CTRL + D.
Definition of ed:
ed :: Bool -> [EdCmdLine] -> IO EdLines
ed xs = concatM $ map toLinesExt $ scanl (flip $ edLine defHs) (return [Leaf ""]) xs where
toLinesExt :: IO [EdState] -> IO EdLines
toLinesExt rsIO = do
rs#(r:_) <- rsIO -- todo add fallback pattern with (error)
return $ fromEd r ++ [" "]
The scanl is definitely evaluated lazy because edLine is getting evaluated for sure (observable by the side effects).
I think it could have to do with concatM:
concatM :: (Foldable t, Monad m) => t (m [a]) -> m [a]
concatM xsIO = foldr (\accIO xIO -> do {x <- xIO; acc <- accIO; return $ acc ++ x}) (return []) xsIO
All I/O in Haskell is explicitly ordered. The last two lines of your main function desugar into something like
ed (lines xs) >>= (\edLines -> putStr $ unlines edLines)
>>= sequences all of the I/O effects on the left before all of those on the right. You're constructing an I/O action of the form generate line 1 >> ... >> generate line n >> output line 1 >> ... >> output line n.
This isn't really an evaluation order issue, it's a correctness issue. An implementation is free to evaluate in any order it wants, but it can't change the ordering of I/O actions that you specified, any more than it can reorder the elements of a list.
Here's a toy example showing what you need to do:
lineProducingActions :: [IO String]
lineProducingActions = replicate 10 getLine
wrongOrder, correctOrder :: IO ()
wrongOrder = do
xs <- sequence lineProducingActions
mapM_ putStrLn xs
correctOrder = do
let xs = [x >>= putStrLn | x <- lineProducingActions]
sequence_ xs
Note that you can decouple the producer and consumer while getting the ordering you want. You just need to avoid combining the I/O actions in the producer. I/O actions are pure values that can be manipulated just like any other values. They aren't side-effectful expressions that happen immediately as they're written. They happen, rather, in whatever order you glue them together in.
You would need to use unsafeInterleaveIO to schedule some of your IO actions for later. Beware that the IO actions may then be executed in a different order than you might first expect!
However, I strongly recommend not doing that. Change your IO [String] action to print each line as it's produced instead.
Alternately, if you really want to maintain the computation-as-pipeline view, check out one of the many streaming libraries available on Hackage (streamly, pipes, iteratees, conduit, machines, and probably half a dozen others).
Thanks to #benrg answer I was able to solve the issue with the following code:
ed :: [EdCmdLine] -> [IO EdLines]
ed cmds = map (>>= return . toLines . head) $ edHistIO where
toLines :: EdState -> EdLines
toLines r = fromEd r ++ [" "]
edHistIO = edRec defHs cmds (return [initState])
edRec :: [HandleHandler] -> [EdCmdLine] -> IO EdHistory -> [IO EdHistory]
edRec _ [] hist = [hist] -- if CTRL + D
edRec defHs (cmd:cmds) hist = let next = edLine defHs cmd hist in next : edRec defHs cmds next
main = getContents >>= mapM_ (>>= (putStr . unlines)) . ed . lines

How can I get output mention in below

readInts = fmap (map read.words) getLine
readInts :: IO [Int]
main = do
putStrLn "List number of A: "
num1 <- readInts
let a = [] ++ num1
putStrLn "List number of B: "
num2 <- readInts
let b = [] ++ num2
Choose some element a of A and some element b of B such that a + b doesn't belong to A and doesn't belong to B
Serious
If your instructor isn't teaching, and that isn't just you being burned out and stressed, then talk to the instructor. They probably aren't trying to waste your and their time. If that doesn't work then talk to the professor.
As for getting homework help here, it is entirely doable but help is very unlikely to appear without some semblance of an attempt and a clear cut issue. You usually need to come to the table with how the problem can be solved and have problems translating that how into the specifics of Haskell or whatever target language.
Cheeky
A cheeky response I'd use if I were in the classroom:
This is a finite domain so I'd just use DPLL. DPLL is a general purpose algorithm for finite domains that allows us to just state the problem as a symbolic computation and constraints then request satisfying models. We'll construct the problem first then use the SBV library to get the model.
Choose some element a of A
So lets define the set A (called as) as a list of symbolics and then constrain an existential to being a member of this set!
a <- exists "value1"
constrain (a `sElem` as)
and some element b of B
OK, same thing. We make a list of symbolic values and constrain an existential to being a member.
b <- exists "value2"
constrain (b `sElem` bs)
such that a + b
Let's define an alias for this:
let c = a + b
doesn't belong to A
We can just reuse the test for membership, sElem, and symbolic negation sNot.
constrain $ sNot (c `sElem` as)
and doesn't belong to B
Yep, same!
constrain $ sNot (c `sElem` bs)
Putting it together
Honestly the hardest part is actually running your problem more than stating it. We need to read the inputs (as you showed), call the solver (sat), and get the answer (aka the "model) via extractModel which can finally be printed.
#!/usr/bin/env cabal
{- cabal:
build-depends:
base, sbv >= 8.4
-}
{-# LANGUAGE ViewPatterns #-}
import Data.SBV
readInts :: IO [Int64]
readInts = fmap read . words <$> getLine
readInt :: IO Int64
readInt = read <$> getLine
main =
do putStrLn "List number of A: "
a <- readInts
putStrLn "List number of B: "
b <- readInts
result <- getValues a b
let values :: Maybe (Int64,Int64)
values = extractModel result
print values
getValues :: [Int64] -> [Int64] -> IO SatResult
getValues (map literal -> as) (map literal -> bs) = sat $
do a <- exists "value1"
constrain (a `sElem` as)
b <- exists "value2"
constrain (b `sElem` bs)
let c = a + b
constrain $ sNot (c `sElem` as)
constrain $ sNot (c `sElem` bs)
Because this uses SBV you'll have to have first installed z3. I included a cabal header to auto build as a package. For example:
brew install z3
...
chmod +x mycode.hs
./mycode.hs
...
List number of A:
1 3 4 5
List number of B:
1 2 3
Just (3,3)

Mixing Either and Maybe Monads

I think I understand how to cascade Monad of the same type. I would like to combine two Monads together to perform an operation based on them :
I think the code below resume the problem : suppose we have a function that validates that a String contains "Jo" and append "Bob" to it if it's the case, and another one that validates that the String length is > 8
The hello function would apply the first , then the second on the result of the first and return "Hello" to all that in case of success or 'Nothing' (I don't know what is this 'Nothing' btw , Left or Nothing) in case of error.
I believe that it's around Monad transformer what I need but I could not find a concise example that would help me to start.
I precise that this is nothing theoratical as there is around Haskell package that works with Either and others that works with Maybe
validateContainsJoAndAppendBob :: String -> Maybe String
validateContainsJoAndAppendBob l =
case isInfixOf "Jo" l of
False -> Nothing
True -> Just $ l ++ "Bob"
validateLengthFunction :: Foldable t => t a -> Either String (t a)
validateLengthFunction l =
case (length l > 8) of
False -> Left "to short"
True -> Right l
-- hello l = do
-- v <- validateContainsJoAndAppendBob l
-- r <- validateLengthFunction v
-- return $ "Hello " ++ r
Use a function to convert Maybe to Either
note :: Maybe a -> e -> Either e a
note Nothing e = Left e
note (Just a) _ = Right a
hello l = do
v <- validateContainsJoAndAppendBob l `note` "Does not contain \"Jo\""
r <- validateLengthFunction v
return $ "Hello " ++ r
In addition to the practical answer given by Li-yao Xia, there's other alternatives. Here's two.
Maybe-Either isomorphism
Maybe a is isomorphic to Either () a, which means that there's a lossless translation between the two:
eitherFromMaybe :: Maybe a -> Either () a
eitherFromMaybe (Just x) = Right x
eitherFromMaybe Nothing = Left ()
maybeFromEither :: Either () a -> Maybe a
maybeFromEither (Right x) = Just x
maybeFromEither (Left ()) = Nothing
You can use one of these to translate to the other. Since validateLengthFunction returns an error text on failure, it would be a lossy translation to turn its return value into a Maybe String value, so it's better to use eitherFromMaybe.
The problem with that, though, is that this will only give you an Either () String value, and you need an Either String String. You can solve this by taking advantage of Either being a Bifunctor instance. First,
import Data.Bifunctor
and then you can write hello as:
hello :: String -> Either String String
hello l = do
v <-
first (const "Doesn't contain 'Jo'.") $
eitherFromMaybe $
validateContainsJoAndAppendBob l
r <- validateLengthFunction v
return $ "Hello " ++ r
This essentially does the same as Li-yao Xia's answer - a little less practical, but also a little less ad-hoc.
The first function maps the first (left-most) case of an Either value. In this case, if the return value from validateContainsJoAndAppendBob is a Left value, it's always going to be Left (), so you can use const to ignore the () input and return a String value.
This gets the job done:
*Q49816908> hello "Job, "
Left "to short"
*Q49816908> hello "Cool job, "
Left "Doesn't contain 'Jo'."
*Q49816908> hello "Cool Job, "
Right "Hello Cool Job, Bob"
This alternative I prefer to the next one, but just for completeness' sake:
Monad transformers
Another option is using Monad transformers. You can either wrap the Maybe in an EitherT, or conversely wrap an Either in MaybeT. The following example does the latter.
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Maybe (MaybeT(..))
helloT :: String -> MaybeT (Either String) String
helloT l = do
v <- MaybeT $ return $ validateContainsJoAndAppendBob l
r <- lift $ validateLengthFunction v
return $ "Hello " ++ r
This also works, but here you still have to deal with the various combinations of Just, Nothing, Left, and Right:
*Q49816908> helloT "Job, "
MaybeT (Left "to short")
*Q49816908> helloT "Cool job, "
MaybeT (Right Nothing)
*Q49816908> helloT "Cool Job, "
MaybeT (Right (Just "Hello Cool Job, Bob"))
If you want to peel off the MaybeT wrapper, you can use runMaybeT:
*Q49816908> runMaybeT $ helloT "Cool Job, "
Right (Just "Hello Cool Job, Bob")
In most cases, I'd probably go with the first option...
What you want is (in the categorical sense) a natural transformation from Maybe to Either String, which the maybe function can provide.
maybeToEither :: e -> Maybe a -> Either e a
maybeToEither e = maybe (Left e) Right
hello l = do
v <- maybeToEither "No Jo" (validateContainsJoAndAppendBob l)
r <- validateLengthFunction v
return $ "Hello " ++ r
You can use <=< from Control.Monad to compose the two validators.
hello l = do
r <- validateLengthFunction <=< maybeToEither "No Jo" . validateContainsJoAndAppendBob $ l
return $ "Hello " ++ r
You can also use >=> and return to turn the whole thing into a single monstrous point-free definition.
hello = maybeToEither "No Jo" . validateContainsJoAndAppendBob
>=> validateLengthFunction
>=> return . ("Hello " ++)

list monad transformer

I need to use a list monad transformer. I've read that there are potential problems with ListT IO from Control.Monad.List, since IO isn't commutative, so I'm looking at ListT done right. But I'm getting some unexpected behavior.
Consider this simple test:
test = runListT $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
Using Control.Monad.List:
Main> test
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)
[(),(),(),(),(),(),(),(),()]
Using "ListT done right":
Main> test
1
(1,6)
Is this a problem with "ListT done right", or am I just using it wrong? Is there a preferred alternative?
Thanks!
This might be intensional on the part of the author, since they say
it lets each element of the list have its own side effects, which only get
`excecuted' if this element of the list is really inspected.
I'm not sure, though. Anyway, you can use this function to sequence the whole
list:
runAll_ :: (Monad m) => ListT m a -> m ()
runAll_ (ListT m) = runAll_' m where
runAll_' m = do
mm <- m
case mm of
MNil -> return ()
_ `MCons` mxs -> runAll_' mxs
And an analogous runAll that returns a list should be easy to construct.
main = runAll_ $ do
x <- liftList [1..3]
liftIO $ print x
y <- liftList [6..8]
liftIO $ print (x,y)
1
(1,6)
(1,7)
(1,8)
2
(2,6)
(2,7)
(2,8)
3
(3,6)
(3,7)
(3,8)

Resources