I am using the Haskeline package and I want to get three strings in a row from the command line before I do anything and I have come up with what seems to be a neat solution to me. But I am sure that there might be a better way to do it. I am looking for best practices while using the Haskeline package. Please evaluate the merits of the following example code:
import System.Console.Haskeline
import Control.Monad.Trans
import Control.Monad.Maybe
import Data.Maybe
import Control.Monad
main :: IO ()
main = runInputT defaultSettings (runMaybeT getStrings) >>= print
getStrings :: MaybeT (InputT IO) (String, String, String)
getStrings = do
mone <- lift $ getInputLine "food> "
notNothing mone
mtwo <- lift $ getInputLine "drink> "
notNothing mtwo
mthree <- lift $ getInputLine "dessert> "
notNothing mthree
return (fromJust mone, fromJust mtwo, fromJust mthree)
where
notNothing a = guard (a /= Nothing)
As you can see it accomplishes the task of early termination but it looks a bit yucky still. I'm thinking of trying to convert the notNothing's and the getInputLine's into a single line like:
mone <- notNothing =<< lift $ getInputLine "food> " -- does not type check
Which I think does not look that bad. I think that is pretty clear and concise (though it does not type check so I will have to write a version that does).
However, this is the best I have come up with and my question finally is: How would you go about improving this code to be neater and more readily readable? Am I even on the right track?
Edit: If your guard is something other than 'a /= Nothing' then a nice helper function that I just discovered is:
myGuard s = guard (someConditionFunc s) >> s
Because then you can write (as luqui suggested):
mone <- myGuard =<< (lift $ getInputLine prompt)
Which is pretty cool. But if you are matching against only Nothing then TomMD's answer is better.
Why not just leverage the fact that fail _ = Nothing for the Maybe monad?
mthree <- lift $ getInputLine "dessert> "
notNothing mthree
becomes
Just mthree <- lift $ getInputLine "dessert> "
How about a helper function?
inputLine :: String -> MaybeT (InputT IO) String
inputLine prompt = do
m <- lift $ getInputLine prompt
case m of
Just x -> return x
Nothing -> mzero
This can be shortened considerably using various tricks, but I wanted to be clear. Now you can just forget that getInputLine can fail, MaybeT takes care of that for you.
Related
I am trying to get a good grip on the do notation in Haskell.
I could use it with Maybe and then print the result. Like this:
maybeAdd :: Maybe Integer
maybeAdd = do one <- maybe1
two <- maybe2
three <- maybe3
return (one + two + three)
main :: IO ()
main = putStr (show $ fromMaybe 0 maybeAdd)
But instead of having a separate function I am trying to use the do notation with the Maybe inside the main function. But I am not having any luck. The various attempts I tried include:
main :: IO ()
main = do one <- maybe1
two <- maybe2
three <- maybe3
putStr (show $ fromMaybe 0 $ return (one + two + three))
main :: IO ()
main = do one <- maybe1
two <- maybe2
three <- maybe3
putStr (show $ fromMaybe 0 $ Just (one + two + three))
main :: IO ()
main = do one <- maybe1
two <- maybe2
three <- maybe3
putStr (show $ (one + two + three))
All of these leads to various types of compilation errors, which unfortunately I failed to decipher to get the correct way to do it.
How do I achieve the above? And perhaps maybe an explanation of why the approaches I tried were wrong also?
Each do block must work within a single monad. If you want to use multiple monads, you could use multiple do blocks. Trying to adapt your code:
main :: IO ()
main = do -- IO block
let x = do -- Maybe block
one <- maybe1
two <- maybe2
three <- maybe3
return (one + two + three)
putStr (show $ fromMaybe 0 x)
You could even use
main = do -- IO block
putStr $ show $ fromMaybe 0 $ do -- Maybe block
one <- maybe1
two <- maybe2
three <- maybe3
return (one + two + three)
-- other IO actions here
but it could be less readable in certain cases.
The MaybeT monad transformer would come handy in this particular case. MaybeT monad transformer is just a type defined something like;
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
Actually transformers like MaybeT, StateT etc, are readily available in Control.Monad.Trans.Maybe, Control.Monad.Trans.State... For illustration purposes it' Monad instance could be something like shown below;
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . Just
x >>= f = MaybeT $ runMaybeT x >>= g
where
g Nothing = return Nothing
g (Just x) = runMaybeT $ f x
so as you will notice the monadic f function takes a value that resides in the Maybe monad which itself is in another monad (IO in our case). The f function does it's thing and wraps the result back into MaybeT m a.
Also there is a MonadTrans class where you can have some common functionalities those are used by the transformer types. One such is lift which is used to lift the value into a transformer according to that particular instance's definition. For MaybeT it should look like
instance MonadTrans MaybeT where
lift = MaybeT . (liftM Just)
Lets perform your task with monad transformers.
addInts :: MaybeT IO ()
addInts = do
lift $ putStrLn "Enter two integers.."
i <- lift getLine
guard $ test i
j <- lift getLine
guard $ test j
lift . print $ (read i :: Int) + (read j :: Int)
where
test = and . (map isDigit)
So when called like
λ> runMaybeT addInts
Enter two integers..
1453
1571
3024
Just ()
The catch is, since a monad transformer is also a member of Monad typeclass, one can nest them indefinitelly and still do things under a singe do notation.
Edit: answer gets downvoted but it is unclear to me why. If there is something wrong with the approach please care to elaborate me so that it helps people including me to learn something better.
Taking the opportunity of being on the edit session, i would like to add a better code since i think Char based testing might not be the best idea as it will not take negative Ints into account. So let's try using readMaybe from the Text.Read package while we are doing things with the Maybe type.
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Class (lift)
import Text.Read (readMaybe)
addInts :: MaybeT IO ()
addInts = do
lift $ putStrLn "Enter two integers.."
i <- lift getLine
MaybeT $ return (readMaybe i :: Maybe Int)
j <- lift getLine
MaybeT $ return (readMaybe j :: Maybe Int)
lift . print $ (read i :: Int) + (read j :: Int)
I guess now it works better...
λ> runMaybeT addInts
Enter two integers..
-400
500
100
Just ()
λ> runMaybeT addInts
Enter two integers..
Not an Integer
Nothing
I want to have the "return" (in imperative language) function in haskell.
E.g.
main = do
let a = 10
print a
-- return this function
print $ a + 1
How can I achieve this?
You can emulate this to some extent using Exceptions,
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Exception
import Data.Typeable
data MyException = MyException deriving (Show, Typeable)
instance Exception MyException
main = handle (\ MyException -> return ()) $ do
let a = 10 :: Int
print a
throwIO MyException
print $ a + 1 -- never gets executed
You can also do it with the ContT or ErrorT monad transformers, although they can a bit unwieldly.
First, let me start by warning that trying to translate imperative constructs into Haskell will likely lead to code which is not idiomatic, hard to write, and hard to read. Just because you can simulate some constructs by using a few monad transformers, it does not mean that this should actually be done.
That being said, here's an example of early return using Control.Monad.Cont.ContT. The code below simulates an imperative return inside a few for loops.
As Rufflewind warns, this can get unwieldy. The type of callCC alone (not shown below) can be quite puzzling.
import Control.Monad.Cont
search :: Int -> IO (Maybe (Int,Int))
search x = runContT (callCC go) return
where go earlyReturn = do
forM_ [10..50] $ \i -> do
lift $ putStrLn $ "Trying i=" ++ show i
forM_ [10..50] $ \j -> do
lift $ putStrLn $ "Trying j=" ++ show j
when (i * j == x) $ do
lift $ putStrLn $ "Found " ++ show (i,j)
earlyReturn $ Just (i,j)
return Nothing
import Picosat
import Control.Applicative
main :: IO ()
main = do
dimacsList1 <- (read <$> getLine) :: IO [[Integer]]
dimacsList2 <- (read <$> getLine) :: IO [[Integer]]
res1 <- solve dimacsList1
res2 <- solve dimacsList2
putStrLn $ (show res1) ++ " " ++ (show res2)
Question: How can I change the above example to run the two sat calls in parallel, i.e., using concurrency? I am interested in performance, if there are different options.
(Just to check: As I understand it, the ST monad is orthogonal and cannot be used in conjunction with parallelization/concurrency. The ST monad confused me a bit in the beginning, is is one of the reasons I ask the question.)
The easiest approach is to use the async library. Something like this, maybe.
[res1, res2] <- mapConcurrently solve [dimacsList1, dimacsList2]
The current version of the Pipes tutorial, uses the following two functions in one of the example:
stdout :: () -> Consumer String IO r
stdout () = forever $ do
str <- request ()
lift $ putStrLn str
stdin :: () -> Producer String IO ()
stdin () = loop
where
loop = do
eof <- lift $ IO.hIsEOF IO.stdin
unless eof $ do
str <- lift getLine
respond str
loop
As is mentinoed in the tutorial itself, P.stdin is a bit more complicated due to the need to check for the end of input.
Are there any nice ways to rewrite P.stdin to not need a manual tail recursive loop and use higher order control flow combinators like P.stdout does? In an imperative language I would use a structured while loop or a break statement to do the same thing:
while(not IO.isEOF(IO.stdin) ){
str <- getLine()
respond(str)
}
forever(){
if(IO.isEOF(IO.stdin) ){ break }
str <- getLine()
respond(str)
}
I prefer the following:
import Control.Monad
import Control.Monad.Trans.Either
loop :: (Monad m) => EitherT e m a -> m e
loop = liftM (either id id) . runEitherT . forever
-- I'd prefer 'break', but that's in the Prelude
quit :: (Monad m) => e -> EitherT e m r
quit = left
You use it like this:
import Pipes
import qualified System.IO as IO
stdin :: () -> Producer String IO ()
stdin () = loop $ do
eof <- lift $ lift $ IO.hIsEOF IO.stdin
if eof
then quit ()
else do
str <- lift $ lift getLine
lift $ respond str
See this blog post where I explain this technique.
The only reason I don't use that in the tutorial is that I consider it less beginner-friendly.
Looks like a job for whileM_:
stdin () = whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) (lift getLine >>= respond)
or, using do-notation similarly to the original example:
stdin () =
whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) $ do
str <- lift getLine
respond str
The monad-loops package offers also whileM which returns a list of intermediate results instead of ignoring the results of the repeated action, and other useful combinators.
Since there is no implicit flow there is no such thing like "break". Moreover your sample already is small block which will be used in more complicated code.
If you want to stop "producing strings" it should be supported by your abstraction. I.e. some "managment" of "pipes" using special monad in Consumer and/or other monads that related with this one.
You can simply import System.Exit, and use exitWith ExitSuccess
Eg. if (input == 'q')
then exitWith ExitSuccess
else print 5 (anything)
Because I oversimplified in my other question before, I would like to give a more clear example here.
How can I handle situations where I have to check for certian conditions in a sequential way without nesting multiple cases? With "sequential way" I mean getting a value (e.g. from stdin), checking this value for a certain condition and depending on the outcome getting another value and so on.
Example:
sequen :: IO String
sequen = do
a <- getLine
case a of
"hi" -> do
putStrLn "hello!"
b <- getLine
case b of
"how are you?" -> do
putStrLn "fine, thanks"
return "nice conversation"
_ -> return "error 2"
_ -> return "error 1"
I know that there are better ways to write such a chat bot, it should just demonstrate the sequential nature of the problem. As you can see, with every nested case, the code also gets indented deeper.
Is there a way to better structure such code? I'm thinking of handling the "errors" on one place and describing the "success-path" without the error handling distributed all over it.
Of course. This is precisely what EitherT was made for. You can get it from Control.Monad.Trans.Either in the eitherT package.
import Control.Monad.Trans.Class
import Control.Monad.Trans.Either
main = do
e <- runEitherT $ do
a <- lift getLine
case a of
"hi" -> lift $ putStrLn "hello!"
_ -> left 1
b <- lift getLine
case b of
"how are you?" -> lift $ putStrLn "fine, thanks!"
_ -> left 2
return "nice conversation"
case e of
Left n -> putStrLn $ "Error - Code: " ++ show n
Right str -> putStrLn $ "Success - String: " ++ str
EitherT aborts the current code block whenever it encounters a left statement, and people typically use this to indicate error conditions.
The inner block's type is EitherT Int IO String. When you runEitherT it, you get IO (Either Int String). The Left type corresponds to the case where it failed with a left and the Right value means it successfully reached the end of the block.
I wrote a series of posts a while back going over my own learnings of the Either & EitherT types. You can read it here: http://watchchrislearn.com/blog/2013/12/01/working-entirely-in-eithert/
I use the errors package to get a bunch of nice helpers around using EitherT (left and right functions for instance to return lifted versions of Left and Right).
By extracting your potential failure conditions into their own helpers, you can make the mainline of your code read totally sequentially, with no case statements checking results.
From that post, you can see how the runEitherT section is a sequential chunk of work, it just happens to have the failure mechanics of EitherT. Obviously this code is fairly contrived to show how MaybeT plays inside of EitherT as well. In real code it'd just be the story you were wanting to tell, with a single Left/Right at the end.
import Control.Error
import Control.Monad.Trans
-- A type for my example functions to pass or fail on.
data Flag = Pass | Error
main :: IO ()
main = do
putStrLn "Starting to do work:"
result <- runEitherT $ do
lift $ putStrLn "Give me the first input please:"
initialText <- lift getLine
x <- eitherFailure Error initialText
lift $ putStrLn "Give me the second input please:"
secondText <- lift getLine
y <- eitherFailure Pass (secondText ++ x)
noteT ("Failed the Maybe: " ++ y) $ maybeFailure Pass y
case result of
Left val -> putStrLn $ "Work Result: Failed\n " ++ val
Right val -> putStrLn $ "Work Result: Passed\n " ++ val
putStrLn "Ok, finished. Have a nice day"
eitherFailure :: Monad m => Flag -> String -> EitherT String m String
eitherFailure Pass val = right $ "-> Passed " ++ val
eitherFailure Error val = left $ "-> Failed " ++ val
maybeFailure :: Monad m => Flag -> String -> MaybeT m String
maybeFailure Pass val = just $ "-> Passed maybe " ++ val
maybeFailure Error _ = nothing
Since you are necessarily in the IO monad, you are better off using the IO monad's error handling capabilities instead of stacking an error monad on top of IO. It avoids all of the heavy lifting:
import Control.Monad ( unless )
import Control.Exception ( catch )
import Prelude hiding ( catch )
import System.IO.Error ( ioeGetErrorString )
main' = do
a <- getLine
unless (a == "hi") $ fail "error 1"
putStrLn "hello!"
b <- getLine
unless (b == "how are you?") $ fail "error 2"
putStrLn "fine, thanks"
return "nice conversation"
main = catch main' $ return . ioeGetErrorString
In this case, your errors are simply Strings, which are thrown by IO's fail, as a userError. If you want to throw some other type, you will need to use throwIO instead of fail.
At some point the EitherT package was deprecated (though transformers-either offers a similar API). Fortunately there's an alternative to EitherT that doesn't even require installing a separate package.
The standard Haskell installation comes with the Control.Monad.Trans.Except module (from the transformers package, which is bundled with GHC), which behaves almost identically to EitherT. The resulting code is almost identical to the code in Gabriella Gonzalez's answer, but using runExceptT instead of runEitherT and throwE instead of left.
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
main = do
e <- runExceptT $ do
a <- lift getLine
case a of
"hi" -> lift $ putStrLn "hello!"
_ -> throwE 1
b <- lift getLine
case b of
"how are you?" -> lift $ putStrLn "fine, thanks!"
_ -> throwE 2
return "nice conversation"
case e of
Left n -> putStrLn $ "Error - Code: " ++ show n
Right str -> putStrLn $ "Success - String: " ++ str
(Note that the aforementioned transformers-either package is in fact a wrapper for ExceptT designed for providing compatibility with code that still uses EitherT.)
Warning: fellow Haskell newbie answering.
You can avoid this sort of staircasing with the Maybe monad. Good example at the start of this chapter
However, you'd want something similar with a monadic Either (presumably there is one) since you're returning error codes.
The basic idea being that once you've got a "Left 1" error you'll short-circuit any future steps (because of lazy evaluation).