Haskell wiki has the following question:
https://en.wikibooks.org/wiki/Haskell/Higher-order_functions
for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO ()
for i p f job = -- ???
I was able to come up with the following implementation:
generate :: a -> (a->Bool) -> (a->a) -> [a]
generate s cnd incr = if (cnd s) then [] else [s] ++ generate (incr s) cnd incr
-- collapse :: [IO ()] -> IO ()
-- collapse (x:xs) = x ++ collapse xs
-- does not work ^^^^^^
for::a->(a->Bool)->(a->a)->(a->IO())->IO()
for s cnd incr ioFn = map (ioFn) (generate s cnd incr)
Ofcourse map (ioFn) (generate s cnd incr) results in [IO ()]. I am not sure how this can be transformed to IO ()
I need something like foldl but the one that works with [IO ()] instead of [a].
The function you are looking for is:
sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
But we can actually just replace map, such that we do not need an extra function. You can use mapM_ :: Monad m => (a -> m b) -> [a] -> m () here instead of map, so:
for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO()
for s cnd incr ioFn = mapM_ ioFn (generate s cnd incr)
This thus will apply the function ioFun on all elements of generate s cnd incr, and eventually return the unit ().
Related
What follows is a series of examples/exercises upon Lenses (by Edward Kmett) in MonadState, based on the solution of Petr Pudlak to my previous question.
In addition to demonstrate some uses and the power of the lenses, these examples show how difficult it is to understand the type signature generated by GHCi. There is hope that in the future things will improve?
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
import Control.Lens
import Control.Monad.State
---------- Example by Petr Pudlak ----------
-- | An example of a universal function that modifies any lens.
-- It reads a string and appends it to the existing value.
modif :: Lens' a String -> StateT a IO ()
modif l = do
s <- lift getLine
l %= (++ s)
-----------------------------------------------
The following comment type signatures are those produced by GHCi.
The other are adaptations from those of Peter.
Personally, I am struggling to understand than those produced by GHCi, and I wonder: why GHCi does not produce those simplified?
-------------------------------------------
-- modif2
-- :: (Profunctor p, MonadTrans t, MonadState s (t IO)) =>
-- (Int -> p a b) -> Setting p s s a b -> t IO ()
modif2 :: (Int -> Int -> Int) -> Lens' a Int -> StateT a IO ()
modif2 f l = do
s<- lift getLine
l %= f (read s :: Int)
---------------------------------------
-- modif3
-- :: (Profunctor p, MonadTrans t, MonadState s (t IO)) =>
-- (String -> p a b) -> Setting p s s a b -> t IO ()
modif3 :: (String -> Int -> Int) -> Lens' a Int -> StateT a IO ()
modif3 f l = do
s <- lift getLine
l %= f s
-- :t modif3 (\n -> (+) (read n :: Int)) == Lens' a Int -> StateT a IO ()
---------------------------------------
-- modif4
-- :: (Profunctor p, MonadTrans t, MonadState s (t IO)) =>
-- (t1 -> p a b) -> (String -> t1) -> Setting p s s a b -> t IO ()
modif4 :: (Bool -> Bool -> Bool) -> (String -> Bool) -> Lens' a Bool -> StateT a IO ()
modif4 f f2 l = do
s <- lift getLine
l %= f (f2 s)
-- :t modif4 (&&) (\s -> read s :: Bool) == Lens' a Bool -> StateT a IO ()
---------------------------------------
-- modif5
-- :: (Profunctor p, MonadTrans t, MonadState s (t IO)) =>
-- (t1 -> p a b) -> (String -> t1) -> Setting p s s a b -> t IO ()
modif5 :: (b -> b -> b) -> (String -> b) -> Lens' a b -> StateT a IO ()
modif5 f f2 l = do
s<- lift getLine
l %= f (f2 s)
-- :t modif5 (&&) (\s -> read s :: Bool) == Lens' a Bool -> StateT a IO ()
---------------------------------------
-- modif6
-- :: (Profunctor p, MonadState s m) =>
-- (t -> p a b) -> (t1 -> t) -> t1 -> Setting p s s a b -> m ()
modif6 :: (b -> b -> b) -> (c -> b) -> c -> Lens' a b -> StateT a IO ()
modif6 f f2 x l = do
l %= f (f2 x)
-- :t modif6 (&&) (\s -> read s :: Bool) "True" == MonadState s m => Setting (->) s s Bool Bool -> m ()
-- :t modif6 (&&) (\s -> read s :: Bool) "True"
---------------------------------------
-- modif7
-- :: (Profunctor p, MonadState s IO) =>
-- (t -> p a b) -> (String -> t) -> Setting p s s a b -> IO ()
modif7 :: (b -> b -> b) -> (String -> b) -> Lens' a b -> StateT a IO ()
modif7 f f2 l = do
s <- lift getLine
l %= f (f2 s)
-- :t modif7 (&&) (\s -> read s :: Bool) ==
-- :t modif7 (+) (\s -> read s :: Int) ==
---------------------------------------
p7a :: StateT Int IO ()
p7a = do
get
modif7 (+) (\s -> read s :: Int) id
test7a = execStateT p7a 10 -- if input 30 then result 40
---------------------------------------
p7b :: StateT Bool IO ()
p7b = do
get
modif7 (||) (\s -> read s :: Bool) id
test7b = execStateT p7b False -- if input "True" then result "True"
---------------------------------------
data Test = Test { _first :: Int
, _second :: Bool
}
deriving Show
$(makeLenses ''Test)
dataTest :: Test
dataTest = Test { _first = 1, _second = False }
monadTest :: StateT Test IO String
monadTest = do
get
lift . putStrLn $ "1) modify \"first\" (Int requested)"
lift . putStrLn $ "2) modify \"second\" (Bool requested)"
answ <- lift getLine
case answ of
"1" -> do lift . putStr $ "> Write an Int: "
modif7 (+) (\s -> read s :: Int) first
"2" -> do lift . putStr $ "> Write a Bool: "
modif7 (||) (\s -> read s :: Bool) second
_ -> error "Wrong choice!"
return answ
testMonadTest :: IO Test
testMonadTest = execStateT monadTest dataTest
As a family in the ML tradition, Haskell is specifically designed so that every toplevel binding has a most general type, and the Haskell implementation can and has to infer this most general type. This ensures that you can reuse the binding in as much places as possible. In a way, this means that type inference is never wrong, because whatever type you have in mind, type inference will figure out the same type or a more general type.
why GHCi does not produce those simplified?
It figures out the more general types instead. For example, you mention that GHC figures out the following type for some code:
modif2 :: (Profunctor p, MonadTrans t, MonadState s (t IO)) =>
(Int -> p a b) -> Setting p s s a b -> t IO ()
This is a very general type, because every time I use modif2, I can choose different profunctors p, monad transformers t and states s. So modif2 is very reusable. You prefer this type signature:
modif2 :: (Int -> Int -> Int) -> Lens' a Int -> StateT a IO ()
I agree that this is more readable, but also less generic: Here you decided that p has to be -> and t has to be StateT, and as a user of modif2, I couldn't change that.
There is hope that in the future things will improve?
I'm sure that Haskell will continue to mandate most general types as the result of type inference. I could imagine that in addition to the most general type, ghci or a third-party tool could show you example instantiations. In this case, it would be nice to declare somehow that -> is a typical profunctor. I'm not aware of any work in this direction, though, so there is not much hope, no.
Let's look at your first example:
modif :: Lens' a String -> StateT a IO ()
modif l = do
s <- lift getLine
l %= (++ s)
This type is simple, but it has also has a shortcoming: You can only use your function passing a Lens. You cannot use your function when you have an Iso are a Traversal, even though this would make perfect sense! Given the more general type that GHCi inferes, you could for example write the following:
modif _Just :: StateT (Maybe String) IO ()
which would append the read value only if that state was a Just, or
modif traverse :: StateT [String] IO ()
which would append the read value to all elements in the list. This is not possible with the simple type you gave, because _Just and traverse are not lenses, but only Traversals.
I have a function that I want to use a Maybe val with. Usually I would do func <$> val. But now suppose that func uses the IO monad. func <$> val will return a Maybe (IO ()). So instead I had to define a new operator:
(<$$>) :: Monad m => (a -> m b) -> Maybe a -> m ()
(<$$>) func (Just val) = func val >> return ()
(<$$>) func Nothing = return ()
So now I can write func <$$> val, but is there a better way to do it?
mapM_ from Data.Foldable is probably the best match:
Prelude Data.Foldable> :set -XScopedTypeVariables
Prelude Data.Foldable> :t \f (a :: Maybe a) -> Data.Foldable.mapM_ f a
\f (a :: Maybe a) -> Data.Foldable.mapM_ f a
:: Monad m => (a -> m b) -> Maybe a -> m ()
If you'd like a more specialised type there's also maybe:
Prelude> :t \f -> maybe (return ()) (f $)
\f -> maybe (return ()) (f $)
:: Monad m => (a -> m ()) -> Maybe a -> m ()
Your <$$> is traverse_ from Data.Foldable.
Is a one-liner always better? Here's how purity of undefined can be useful:
(<$$>) g x = maybe (return undefined) g x >> return ()
Example:
Prelude> print <$$> (Just 1)
1
Prelude> print <$$> Nothing
Prelude>
If you have a lot of this in your code, it might be worth employing the MaybeT transformer:
(\func val -> liftIO . func =<< MaybeT (return val) )
:: (a -> IO b) -> Maybe b -> MaybeT IO b
That doesn't immediately bring you any further than plain IO (Maybe ()), but it composes nicely.
I have a function which signature is String -> String -> IO (Maybe String)
Now, I use this function to build values for a dictionary and I end up with: [(String,IO (Maybe String))]
I have to analyze the values in the dictionary and based on the result return the appropriate key. I was hoping to just use filter on the Map to step through it but I can't think of a way to extract that IO action on the fly. So how do I map/filter through the dictionary running the IO action and based on the result of the IO action's value return appropriate key of the dictionary?? Is there an easy way of doing it or I just got myself in a mess?
Thanks.
Perhaps the solution is to use sequence with something like
sequence . map (\(a,mb) -> (mb >>= \b -> return (a,b)))
then you can simply use liftM to apply your filter to the resulting IO [(String,Maybe String)].
liftM is in Control.Monad. Alternatively, in do notation
myFilter :: (String,(Maybe String)) -> Bool)
-> [(String,IO (Maybe String))]
-> IO [(String,(Maybe String))]
myFilter f ml =
do
l <- sequence . map (\(a,mb) -> (mb >>= \b -> return (a,b))) $ ml
return $ filter f ml
Perhaps some refactoring is in order. Often when working with monads you want to use mapM instead of map.
There is also a filterM function in Control.Monad. It might be what you need.
Edit: it was pointed out in comments that
sequence . map (\(a,mb) -> (mb >>= \b -> return (a,b))) $ ml
is equivalent to
mapM (\(a,mb) -> fmap ((,) a) mb) ml
so
myFiter' f = (liftM $ filter f) . mapM (\(a,mb) -> fmap ((,) a) mb)
I have a function which signature is String -> String -> IO (Maybe String) Now, I use this function to build values for a dictionary and I end up with: [(String,IO (Maybe String))]
This part doesn't add up for me. How do you input only 2 strings, and end up with a meaningful result of type [(String, IO (Maybe String))]?
Lacking the particulars, lets assume your situation is something like this:
f :: String -> String -> IO (Maybe String)
magic :: String -> (String, String)
magic takes some key, and somehow splits the key into the two input strings needed by f. So, assuming you have a list of keys, you would wind up with a [(String, IO (Maybe String))] like this:
-- ks :: [String]
myMap = map (\k -> let (a,b) = magic k in (k, f a b)) ks
But...wouldn't it be so much nicer if we had a [(String, Maybe String)] instead? Assuming we're inside an IO action...
someIOAction = do
...
myMap <- monadicMagicks (\k -> let (a,b) = magic k in (k, f a b)) ks
But what monadicMagicks could we use to make this work out right? Let's look at the types that we expect from these expressions
monadicMagicks (\k -> ...) ks :: IO [(String, Maybe String)]
(\k -> let (a,b) = magic k in (k, f a b)) :: String -> (String, IO (Maybe String))
ks :: [String]
-- therefore
monadicMagicks :: (String -> (String, IO (Maybe String)))
-> [String]
-> IO [(String, Maybe String)]
Stop...Hoogle time. Let's generalize what we're looking for a bit, first. We have two basic data types here: String, which appears to be the "input", and Maybe String, which appears to be the "output". So let's replace String with a and Maybe String with b. So we're looking for (a -> (a, IO b)) -> [a] -> IO [(a, b)]. Hrm. No results found. Well, if we could get a result type of just IO [b], then in a do block we could get it out of IO, and then zip it with the original key list. That also means the function we put in wouldn't have to perform the pairing of key with result. So let's simplify what we're looking for and try again: (a -> IO b) -> [a] -> IO [b]. Hey, check it out! mapM matches that type signature perfectly.
monadicMagicks :: (a -> IO b) -> [a] -> IO [(a, b)]
monadicMagicks f xs = do
ys <- mapM f xs
return $ zip xs ys
This could actually be written more succinctly, and with a more general type signature:
monadicMagicks :: Monad m => (a -> m b) -> [a] -> m [(a, b)]
monadicMagicks f xs = zip xs `liftM` mapM f xs
someIOAction = do
...
-- Like we said, the lambda no longer has to pair up the key with the result
myMap <- monadicMagicks (\k -> let (a,b) = magic k in f a b) ks
This last line could also be rewritten a bit shorter, if you're comfortable with function composition:
myMap <- monadicMagicks (uncurry f . magic) ks
Note that monadicMagicks might not make much sense for some monads, which is probably why it isn't in the standard libs. (For example, using mapM in the list monad usually means that the result will have a different length than the input):
ghci> mapM (\x -> [x, -x]) [1,2]
[[1,2],[1,-2],[-1,2],[-1,-2]]
findM :: Monad m => (a -> m Bool) -> m [a] -> Maybe (m a)
I cannot implement it by myself. I could use some pointers
find looks like:
find f as = listToMaybe $ filter f as
so I tried:
findM f as = filterM f as >>= listToMaybe
but it doesnt work.
No. It is not possible. However, you can write a function with the signature:
findM :: Monad m => (a -> m Bool) -> m [a] -> m (Maybe a)
The reason it is not possible is because in order to figure out if the Maybe has constructor Just x or Nothing, you have to get the value out of the monad. Which means that the Maybe must be inside the monad at the end, since it is not possible in general to extract a value from inside a monad. (That is the whole point of monads, after all.)
For example, given your signature to findM, you could write some obviously incorrect functions:
findM :: Monad m => (a -> m Bool) -> m [a] -> Maybe (m a)
findM = magic
anyM :: Monad m => (a -> m Bool) -> m [a] -> Bool
anyM f = isJust . findM f
extractBool :: Monad m => m Bool -> Bool
extractBool = anyM id . liftM (:[])
The function extractBool is obviously impossible, so findM cannot have that signature.
Here is an implementation of findM:
findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
findM _ [] = return Nothing
findM f (x:xs) = do y <- f x
if y then return (Just x) else findM f xs
I am not sure of a simpler way to implement it -- this seems fairly clean, and it works on infinite lists.
Changing the signature from using an m [a] to using [a] makes it more useful and easier to use. You'll quickly figure out why, if you implement both interfaces.
Try
findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
findM p = foldr step (return Nothing)
where
step x r = do
b <- p x
if b then return (Just x) else r
This version only uses the predicate as much as it has to, whereas the filterM version uses it on every element. So for example:
ghci> let findM' p xs = filterM p xs >>= return . listToMaybe
ghci> let check x = putStrLn ("checking " ++ show x) >> doesDirectoryExist x
ghci> findM check ["test1", ".", "test2"]
checking "test1"
checking "."
Just "."
ghci> findM' check ["test1", ".", "test2"]
checking "test1"
checking "."
checking "test2"
Just "."
Others have already demonstrated that this isn't possible, however with a further constraint you can get a very similar function.
findM :: (Traversable m, Monad m) => (a -> m Bool) -> m [a] -> Maybe (m a)
findM p xs = Data.Traverse.sequence $ dietrichsFindM p xs
Not every Monad has a Traversable instance, but if it does this will work.
For the signature
findM :: Monad m => (a -> m Bool) -> m [a] -> m (Maybe a)
i suggest:
import Control.Monad
import Data.Maybe
findM :: Monad m => (a -> m Bool) -> m [a] -> m (Maybe a)
findM f m = m >>= filterM f >>= return . listToMaybe
or
findM :: Monad m => (a -> m Bool) -> m [a] -> m (Maybe a)
findM = ((return . listToMaybe =<<) .) . (=<<) . filterM
for a point-free style.
Is there a traditional way to map over a function that uses IO? Specifically, I'd like to map over a function that returns a random value of some kind. Using a normal map will result in an output of type ([IO b]), but to unpack the values in the list from IO, I need a something of type (IO [b]). So I wrote...
mapIO :: (a -> IO b) -> [a] -> [b] -> IO [b]
mapIO f [] acc = do return acc
mapIO f (x:xs) acc = do
new <- f x
mapIO f xs (new:acc)
... which works fine. But it seems like there ought to be a solution for this built into Haskell. For instance, an example use case:
getPercent :: Int -> IO Bool
getPercent x = do
y <- getStdRandom (randomR (1,100))
return $ y < x
mapIO (\f -> getPercent 50) [0..10] []
The standard way is via:
Control.Monad.mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
which is implemented in terms of sequence:
sequence :: (Monad m) => [m a] -> m [a]
Just to add to Don's answer, hake a look to the mapM_ function as well, which does exactly what mapM does but discards all the results so you get only side-effects.
This is useful if you want the have computations executed (for example IO computations) but are not interested in the result (for example, unlinking files).
And also see forM and forM_.