optparse-applicative with custom monad - haskell

I'm trying to use my own monad (instead of IO) with customExecParser https://hackage.haskell.org/package/optparse-applicative-0.15.1.0/docs/Options-Applicative-Extra.html#v:customExecParser.
So I've ended up with (significant function being fff):
data MoscConfig = MoscConfig {
datadir :: FilePath
, config :: FilePath
, pendingPath :: FilePath
, socket :: FilePath
}
type Mosco = StateT MoscConfig IO
main :: IO ()
main = join . customExecParser (prefs showHelpOnError) $
info (helper <*> parser)
( fullDesc
)
fff :: (a1 -> StateT MoscConfig IO a2) -> a1 -> IO a2
fff f = (flip evalStateT (MoscConfig "" "" "" "")) . f
xyzz :: Text -> Mosco ()
xyzz x = do
liftIO $ print x
liftIO $ print "testabcxyz"
xyzz' :: Text -> Text -> Mosco ()
xyzz' x x' = do
liftIO $ print x
liftIO $ print x'
liftIO $ print "testabcxyz"
parser :: Parser (IO ())
parser = do
fff xyzz <$> textOption ( long "zzz" )
<|>
((fmap fff) xyzz')
<$> textOption ( long "zzz" )
<*> textOption ( long "zzz" )
However, the only disadvantage with the above approach is needing to fmap the required number of times (matching the function arguments in xyzz or xyzz). I do recall running into this type of problem before. Is there some way I can avoid this (and just have a single function needing to be called)?
Ideally I'd hope to have a monad transformer for this but unfortunately this seems to be implemented to IO only.

I think this boils down to the question: is there a function fff that can be applied to both of:
xyzz :: a -> r
xyzz' :: a -> b -> r
so that:
fff xyzz :: a -> r'
fff xyzz' :: a -> b -> r'
And the answer is "no", at least not without some type class trickery that isn't worth considering.
Instead, assuming your real version of fff doesn't actually do anything with f except compose with it, I guess I would consider writing:
fff :: Parser (Mosco a) -> Parser (IO a)
fff = fmap $ flip evalStateT (MoscConfig "" "" "" "")
parser :: Parser (IO ())
parser = fff (xyzz <$> textOption ( long "zzz" ))
<|> fff (xyzz' <$> textOption ( long "zzz" ) <*> textOption ( long "zzz" ))
This whole approach seems a little "off", though. Do you really need a MoscConfig available while parsing options? Unless you have a really complicated options parsing problem on your hands, it would be more usual to parse the options directly into an intermediate data structure and then run your Mosco actions against that data structure to modify a MoscConfig state and do IO and so on.

In terms of what I wanted to achieve (being able to just pass parameters to function within the Mosco monad context -
moscparams ::
Maybe Text
-> Maybe Text
-> Maybe Text
-> Maybe Text
-> Mosco a -> IO a
moscparams dd c pp sp x = do
ddd <- crFile
cd <- pure "not used"
ppd <- crDirPending
spd <- socketFile
evalStateT x
$ MoscConfig
(maybe ddd cs dd)
(maybe cd cs c)
(maybe ppd cs pp)
(maybe spd cs sp)
moscF' :: Text -> Text -> Mosco ()
moscF' x x' = do
liftIO $ print x
liftIO $ print x'
liftIO $ print "testabcxyz"
moscparams' :: Parser (Mosco ()) -> Parser (IO ())
moscparams' x = moscparams
<$> optional (textOption ( long "data-dir" ))
<*> optional (textOption ( long "config-path" ))
<*> optional (textOption ( long "pending-path" ))
<*> optional (textOption ( long "socket-path" ))
<*> x
parser :: Parser (IO ())
parser = do
moscparams'
(( moscF')
<$> textOption ( long "example-param-1" )
<*> textOption ( long "example-param-2" )
)

Related

reading files in Haskell IO Monads

Hello everyone I am beginner in Haskell, I have a dat file that contains
[("img0.bmp", [0,0])
,("img1.bmp", [0,1])
,("img2.bmp", [1,0])
,("img3.bmp", [1,1])]
the strings are images files in a folder so basically I need to read file including many files as inputs , I am trying to have at the end [([Double],[Double])] extracting matrix from bmp files and turn that into [Double]
I have tried something like this
learnbmp = do
vs <- getArgs
df <- run (readFile (vs!!0))
let ds = Prelude.read df :: [(String,[Double])]
let ns = Prelude.unzip ds
--let a = Prelude.map (\(v) -> toUnboxed (readImageFromBMPa v))(fst ns)
let a = fst ns
let b = snd ns
--let n' = Prelude.map (\(v) -> ((readMatrixfromImage v) ) ) a
let n' = Prelude.map (\(v) -> ((readMatrixfromImage v) ) ) a
let final = Prelude.zip n' b
return final
the type of final is
final :: [(IO (Vector Word8), [Double])]
with the function readMatrixfromImage is defined like this
readMatrixfromImage :: FilePath -> IO (Vector Word8)
readMatrixfromImage image = do
x <- readImageFromBMPa image -- 'x' est alors de type t
let (Right r) = x
let a = toUnboxed r
return a
any help would be appreciated thank you
If you want to obtain the results "wrapped" in the IO monad, you can use mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b):
learnbmp :: IO [([Double],[Double])]
learnbmp = do
(v0:_) <- getArgs
df <- run (readFile v0)
let (a, b) = Prelude.unzip (Prelude.read df :: [(String,[Double])])
(`Prelude.zip` b) <$> mapM readMatrixfromImage a
Here the learnbmp thus has type IO [([Double], [Double])]. It is thus an IO action that will result in an item of type [([Double], [Double])], and you can thus use learnbmp in other expressions that result in a type IO a like main.

Point free version for readMaybe

I want to write a function to read an Int without do notation. It works (see below), but I was wondering if it the bit around readMaybe can be written in point free form (or cleaned up a bit in some other way)?
main :: IO ()
main = getLine >>= (\x -> return $ (readMaybe x :: Maybe Int)) >>= print
Step 1: Replace the lambda with its pointfree equivalent:
main :: IO ()
main = getLine >>= return . (readMaybe :: String -> Maybe Int) >>= print
Step 2: Replace m >>= return . f with f <$> m:
main :: IO ()
main = (readMaybe :: String -> Maybe Int) <$> getLine >>= print
Step 3: Replace f <$> m >>= g with m >>= g . f:
main :: IO ()
main = getLine >>= print . (readMaybe :: String -> Maybe Int)
Step 4: Use a type application instead of writing out a long, awkward type:
{-# LANGUAGE TypeApplications #-}
main :: IO ()
main = getLine >>= print . readMaybe #Int
As an alternative to using <$> in steps 2 and 3, you can accomplish the same with just the monad laws, like this (picking up after step 1):
Replace m >>= f >>= g with m >>= \x -> f x >>= g (associativity):
main :: IO ()
main = getLine >>= \x -> (return . (readMaybe :: String -> Maybe Int)) x >>= print
Simplify the . away:
main :: IO ()
main = getLine >>= \x -> return ((readMaybe :: String -> Maybe Int) x) >>= print
Replace return x >>= f with f x (left identity):
main :: IO ()
main = getLine >>= \x -> print ((readMaybe :: String -> Maybe Int) x)
Now just replace that new lambda with its pointfree equivalent, and you end up in the exact same place as step 3.

Why doesn't this simple composition work?

I was recently in need of putting head in between two monadic operations. Here's the SSCCE:
module Main where
f :: IO [Int]
f = return [1..5]
g :: Int -> IO ()
g = print
main = do
putStrLn "g <$> head <$> f"
g <$> head <$> f
putStrLn "g . head <$> f"
g . head <$> f
putStrLn "head <$> f >>= g"
head <$> f >>= g
This program is well-formed and compiles without warnings. However, only one version out of 3 above works1. Why is that?
And specifically, what would be the best way to link f and g together with head in the middle? I ended up using the 3rd one (in the form of do notation), but I don't really like it, since it should be a trivial one-liner2.
1 Spoiler alert: the 3rd one is the only one that prints 1; the other two are silent, both under runhaskell and repl.
2 I do realize that those are all one-liners, but the order of operations feels really confusing in the only one that works.
Probably the best way to write this is:
f >>= g . head
or in a more verbose form:
f >>= (g . head)
so we basically perform an fmap on the value for f (we thus take the head of the values wrapped in the IO monad), and then we pass then to g, like:
(head <$> f) >>= g
is semantically the same.
But now what happens if we use g <$> head <$> f? Let us first analyze the types:
f :: IO [Int]
g :: Int -> IO ()
(<$>) :: Functor m => (a -> b) -> m a -> m b
(I used m here to avoid confusion with the f function)
The canonical form of this is:
((<$>) ((<$>) g head) f)
The second (<$>) takes a g :: Int -> IO () and head :: [c] -> c as parameters, so that means that a ~ Int, b ~ IO (), and m ~ (->) [c]. So the result is:
(<$>) g head :: (->) [c] (IO ())
or less verbose:
g <$> head :: [c] -> IO ()
The first (<$>) function thus takes as parameters g <$> head :: [c] -> IO (), and IO [Int], so that means that m ~ IO, a ~ [Int], c ~ Int, b ~ IO (), and hence we obtain the type:
(<$>) (g <$> head) f :: IO (IO ())
We thus do not perform any real action: we fmap the [Int] list to an IO action (that is wrapped in the IO). You could see it as return (print 1): you do not "evaluate" the print 1, but you return that wrapped in an IO.
You can of course "absorb" the outer IO here, and then use the inner IO, like:
evalIO :: IO (IO f) -> IO f
evalIO res = do
f <- res
f
or shorter:
evalIO :: IO (IO f) -> IO f
evalIO res = res >>= id
(this can be generalized to all sorts of Monads, but this is irrelevant here).
The evalIO is also known as join :: Monad m => m (m a) -> m a.
The first and second are exactly the same, because <$> is left-associative and head is a function, and <$> is . in the function monad. Then,
g . head <$> f
= fmap (print . head) (return [1..5] :: IO [Int])
= do { x <- (return [1..5] :: IO [Int])
; return ( print (head x) ) }
= do { let x = [1..5]
; return ( print (head x) ) } :: IO _whatever
=
return ( print 1 ) :: IO (IO ())
We have one too many returns there. In fact,
= fmap (print . head) (return [1..5] :: IO [Int])
= return (print (head [1..5]))
= return (print 1)
is a shorter derivation.
The third one is
(head <$> f) >>= g
= (fmap head $ return [1..5]) >>= print
= (return (head [1..5])) >>= print
= (return 1) >>= print
which is obviously OK.

Why must we use state monad instead of passing state directly?

Can someone show a simple example where state monad can be better than passing state directly?
bar1 (Foo x) = Foo (x + 1)
vs
bar2 :: State Foo Foo
bar2 = do
modify (\(Foo x) -> Foo (x + 1))
get
State passing is often tedious, error-prone, and hinders refactoring. For example, try labeling a binary tree or rose tree in postorder:
data RoseTree a = Node a [RoseTree a] deriving (Show)
postLabel :: RoseTree a -> RoseTree Int
postLabel = fst . go 0 where
go i (Node _ ts) = (Node i' ts', i' + 1) where
(ts', i') = gots i ts
gots i [] = ([], i)
gots i (t:ts) = (t':ts', i'') where
(t', i') = go i t
(ts', i'') = gots i' ts
Here I had to manually label states in the right order, pass the correct states along, and had to make sure that both the labels and child nodes are in the right order in the result (note that naive use of foldr or foldl for the child nodes could have easily led to incorrect behavior).
Also, if I try to change the code to preorder, I have to make changes that are easy to get wrong:
preLabel :: RoseTree a -> RoseTree Int
preLabel = fst . go 0 where
go i (Node _ ts) = (Node i ts', i') where -- first change
(ts', i') = gots (i + 1) ts -- second change
gots i [] = ([], i)
gots i (t:ts) = (t':ts', i'') where
(t', i') = go i t
(ts', i'') = gots i' ts
Examples:
branch = Node ()
nil = branch []
tree = branch [branch [nil, nil], nil]
preLabel tree == Node 0 [Node 1 [Node 2 [],Node 3 []],Node 4 []]
postLabel tree == Node 4 [Node 2 [Node 0 [],Node 1 []],Node 3 []]
Contrast the state monad solution:
import Control.Monad.State
import Control.Applicative
postLabel' :: RoseTree a -> RoseTree Int
postLabel' = (`evalState` 0) . go where
go (Node _ ts) = do
ts' <- traverse go ts
i <- get <* modify (+1)
pure (Node i ts')
preLabel' :: RoseTree a -> RoseTree Int
preLabel' = (`evalState` 0) . go where
go (Node _ ts) = do
i <- get <* modify (+1)
ts' <- traverse go ts
pure (Node i ts')
Not only is this code more succinct and easier to write correctly, the logic that results in pre- or postorder labeling is far more transparent.
PS: bonus applicative style:
postLabel' :: RoseTree a -> RoseTree Int
postLabel' = (`evalState` 0) . go where
go (Node _ ts) =
flip Node <$> traverse go ts <*> (get <* modify (+1))
preLabel' :: RoseTree a -> RoseTree Int
preLabel' = (`evalState` 0) . go where
go (Node _ ts) =
Node <$> (get <* modify (+1)) <*> traverse go ts
As an example to my comment above, you can write code using the State monad like
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Text (Text)
import qualified Data.Text as Text
import Control.Monad.State
data MyState = MyState
{ _count :: Int
, _messages :: [Text]
} deriving (Eq, Show)
makeLenses ''MyState
type App = State MyState
incrCnt :: App ()
incrCnt = modify (\my -> my & count +~ 1)
logMsg :: Text -> App ()
logMsg msg = modify (\my -> my & messages %~ (++ [msg]))
logAndIncr :: Text -> App ()
logAndIncr msg = do
incrCnt
logMsg msg
app :: App ()
app = do
logAndIncr "First step"
logAndIncr "Second step"
logAndIncr "Third step"
logAndIncr "Fourth step"
logAndIncr "Fifth step"
Note that using additional operators from Control.Lens also lets you write incrCnt and logMsg as
incrCnt = count += 1
logMsg msg = messages %= (++ [msg])
which is another benefit of using State in combination with the lens library, but for the sake of comparison I'm not using them in this example. To write the equivalent code above with just argument passing it would look more like
incrCnt :: MyState -> MyState
incrCnt my = my & count +~ 1
logMsg :: MyState -> Text -> MyState
logMsg my msg = my & messages %~ (++ [msg])
logAndIncr :: MyState -> Text -> MyState
logAndIncr my msg =
let incremented = incrCnt my
logged = logMsg incremented msg
in logged
At this point it isn't too bad, but once we get to the next step I think you'll see where the code duplication really comes in:
app :: MyState -> MyState
app initial =
let first_step = logAndIncr initial "First step"
second_step = logAndIncr first_step "Second step"
third_step = logAndIncr second_step "Third step"
fourth_step = logAndIncr third_step "Fourth step"
fifth_step = logAndIncr fourth_step "Fifth step"
in fifth_step
Another benefit of wrapping this up in a Monad instance is that you can use the full power of Control.Monad and Control.Applicative with it:
app = mapM_ logAndIncr [
"First step",
"Second step",
"Third step",
"Fourth step",
"Fifth step"
]
Which allows for much more flexibility when processing values calculated at runtime compared to static values.
The difference between manual state passing and using the State monad is simply that the State monad is an abstraction over the manual process. It also happens to fit several other widely used more general abstractions, like Monad, Applicative, Functor, and a few others. If you also use the StateT transformer then you can compose these operations with other monads, such as IO. Can you do all of this without State and StateT? Of course you can, and there's no one stopping you from doing so, but the point is that State abstracts this pattern out and gives you access to a huge toolbox of more general tools. Also, a small modification to the types above makes the same functions work in multiple contexts:
incrCnt :: MonadState MyState m => m ()
logMsg :: MonadState MyState m => Text -> m ()
logAndIncr :: MonadState MyState m => Text -> m ()
These will now work with App, or with StateT MyState IO, or any other monad stack with a MonadState implementation. It makes it significantly more reusable than simple argument passing, which is only possible through the abstraction that is StateT.
In my experience, the point of many Monads doesn't really click until you get into larger examples, so here is an example use of State (well, StateT ... IO) to parse an incoming request to a web service.
The pattern is that this web service can be called with a bunch of options of different types, though all except for one of the options have decent defaults. If I get a incoming JSON request with an unknown key value, I should abort with an appropriate message. I use the state to keep track of what the current config is, and what the remainder of the JSON request is, along with a bunch of accessor methods.
(Based on code currently in production, with the names of everything changed and the details of what this service actually does obscured)
{-# LANGUAGE OverloadedStrings #-}
module XmpConfig where
import Data.IORef
import Control.Arrow (first)
import Control.Monad
import qualified Data.Text as T
import Data.Aeson hiding ((.=))
import qualified Data.HashMap.Strict as MS
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.State (execStateT, StateT, gets, modify)
import qualified Data.Foldable as DF
import Data.Maybe (fromJust, isJust)
data Taggy = UseTags Bool | NoTags
newtype Locale = Locale String
data MyServiceConfig = MyServiceConfig {
_mscTagStatus :: Taggy
, _mscFlipResult :: Bool
, _mscWasteTime :: Bool
, _mscLocale :: Locale
, _mscFormatVersion :: Int
, _mscJobs :: [String]
}
baseWebConfig :: IO (IORef [String], IORef [String], MyServiceConfig)
baseWebConfig = do
infoRef <- newIORef []
warningRef <- newIORef []
let cfg = MyServiceConfig {
_mscTagStatus = NoTags
, _mscFlipResult = False
, _mscWasteTime = False
, _mscLocale = Locale "en-US"
, _mscFormatVersion = 1
, _mscJobs = []
}
return (infoRef, warningRef, cfg)
parseLocale :: T.Text -> Maybe Locale
parseLocale = Just . Locale . T.unpack -- The real thing does more
parseJSONReq :: MS.HashMap T.Text Value ->
IO (IORef [String], IORef [String], MyServiceConfig)
parseJSONReq m = liftM snd
(baseWebConfig >>= (\c -> execStateT parse' (m, c)))
where
parse' :: StateT (MS.HashMap T.Text Value,
(IORef [String], IORef [String], MyServiceConfig))
IO ()
parse' = do
let addWarning s = do let snd3 (_, b, _) = b
r <- gets (snd3 . snd)
liftIO $ modifyIORef r (++ [s])
-- These two functions suck a key/value off the input map and
-- pass the value on to the handler "h"
onKey k h = onKeyMaybe k $ DF.mapM_ h
onKeyMaybe k h = do myb <- gets fst
modify $ first $ MS.delete k
h (MS.lookup k myb)
-- Access the "lns" field of the configuration
config setter = modify (\(a, (b, c, d)) -> (a, (b, c, setter d)))
onKey "tags" $ \x -> case x of
Bool True -> config $ \c -> c {_mscTagStatus = UseTags False}
String "true" -> config $ \c -> c {_mscTagStatus = UseTags False}
Bool False -> config $ \c -> c {_mscTagStatus = NoTags}
String "false" -> config $ \c -> c {_mscTagStatus = NoTags}
String "inline" -> config $ \c -> c {_mscTagStatus = UseTags True}
q -> addWarning ("Bad value ignored for tags: " ++ show q)
onKey "reverse" $ \x -> case x of
Bool r -> config $ \c -> c {_mscFlipResult = r}
q -> addWarning ("Bad value ignored for reverse: " ++ show q)
onKey "spin" $ \x -> case x of
Bool r -> config $ \c -> c {_mscWasteTime = r}
q -> addWarning ("Bad value ignored for spin: " ++ show q)
onKey "language" $ \x -> case x of
String s | isJust (parseLocale s) ->
config $ \c -> c {_mscLocale = fromJust $ parseLocale s}
q -> addWarning ("Bad value ignored for language: " ++ show q)
onKey "format" $ \x -> case x of
Number 1 -> config $ \c -> c {_mscFormatVersion = 1}
Number 2 -> config $ \c -> c {_mscFormatVersion = 2}
q -> addWarning ("Bad value ignored for format: " ++ show q)
onKeyMaybe "jobs" $ \p -> case p of
Just (Array x) -> do q <- parseJobs x
config $ \c -> c {_mscJobs = q}
Just (String "test") ->
config $ \c -> c {_mscJobs = ["test1", "test2"]}
Just other -> fail $ "Bad value for jobs: " ++ show other
Nothing -> fail "Missing value for jobs"
m' <- gets fst
unless (MS.null m') (fail $ "Unrecognized key(s): " ++ show (MS.keys m'))
parseJobs :: (Monad m, DF.Foldable b) => b Value -> m [String]
parseJobs = DF.foldrM (\a b -> liftM (:b) (parseJob a)) []
parseJob :: (Monad m) => Value -> m String
parseJob (String s) = return (T.unpack s)
parseJob q = fail $ "Bad job value: " ++ show q

IO inside the Get Monad

So my problem is as follows. I'm trying to implement a streaming parser for RDB files (the dump files that Redis produces). I want to implement a function similar to mapM_ whereby I can , say print out each object represented in the dump file as it is parsed. However, I can't seem to get it to operate in constant space. I find that what is happening is that I'm building a large IO() thunk inside of the Get monad, returning from the Get monad and then executing the IO. Is there anyway to stream my objects as they are parsed to print and then discard them? I've tried Enumerators and Conduits but I haven't seen any real gain. Here is what I have so far:
loadObjs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
loadObjs_ f = do
code <- lookAhead getWord8
case code of
0xfd -> do
skip 1
expire <- loadTime
getPairs_ f (Just expire)
0xfc -> do
skip 1
expire <- loadTimeMs
getPairs_ f (Just expire)
0xfe -> f Nothing "Switching Database" RDBNull
0xff -> f Nothing "" RDBNull
_ -> getPairs_ f Nothing
getPairs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Maybe Integer -> Get (m a)
getPairs_ f ex = do
!t <- getWord8
!key <- loadStringObj False
!obj <- loadObj t
!rest <- loadObjs_ f
!out <- f ex key obj
return (out >> rest)
(loadObj does the actual parsing of a single object but I believe that whatever I need to fix the streaming to operate in constant or near-constant memory is at a higher level in the iteration than loadObj)
getDBs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
getDBs_ f = do
opc <- lookAhead getWord8
if opc == opcodeSelectdb
then do
skip 1
(isEncType,dbnum) <- loadLen
objs <- loadObjs_ f
rest <- getDBs_ f
return (objs >> rest)
else f Nothing "EOF" RDBNull
processRDB_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
processRDB_ f = do
header <- getBytes 9
dbs <- getDBs_ f
eof <- getWord8
return (dbs)
printRDBObj :: Maybe Integer -> BL8.ByteString -> RDBObj -> Get (IO ())
printRDBObj (Just exp) key obj = return $ (print ("Expires: " ++ show exp) >>
print ("Key: " ++ (BL8.unpack key)) >>
print ("Obj: " ++ show obj))
printRDBObj Nothing key RDBNull = return $ (print $ BL8.unpack key)
printRDBObj Nothing key obj = return $ (print ("Key: " ++ (BL8.unpack key)) >>
print ("Obj: " ++ show obj))
main = do
testf <- BL8.readFile "./dump.rdb"
runGet (processRDB_ printRDBObj) testf
Thanks all in advance.
Best,
Erik
EDIT: Here is my attempt to parse the objects into a lazy list and then IO over the lazy list.
processRDB :: Get [RDBObj]
processRDB = do
header <- getBytes 9
dbs <- getDBs
eof <- getWord8
return (dbs)
main = do
testf <- BL8.readFile "./dump.rdb"
mapM_ (print . show) $ runGet processRDB testf
If I understand your code correctly, you are trying to convert the file contents into IO actions incrementally, in the hope of then executing those actions incrementally.
A better approach would be to have your parser return a lazy list of objects which you then print out.

Resources