I have a these three functions
a :: Int -> Maybe Int
a i = if i < 100 then Just i else Nothing
b :: Int -> Maybe Int
b i = if i < 50 then Just i else Nothing
c :: Int -> Maybe Int
c i = if i > 0 then Just i else Nothing
And I want to chain them together so that when the result of one function results in a Nothing the input of that function is returned instead.
I can achieve this with this function:
import Data.Maybe (fromMaybe)
e :: Int -> [Int -> Maybe Int] -> Int
e i [] = i
e i (f:fs) = e (fromMaybe i $ f i) fs
-
*Main> e 75 [a,b,c]
75
Is there an existing function, Monad instance, or other way in the base libraries that exhibits this behavior?
Expanding my comment above -- this approach is not too different from the code the OP posted.
We first define how to turn a function a -> Maybe a into a -> a, substituting the input for Nothing.
totalize :: (a -> Maybe a) -> (a -> a)
totalize f x = fromMaybe x (f x)
Then, we exploit the above: we make every function "total" (meaning no-Nothings), wrap it as an Endo, then we compose the list of endomorphisms (mconcat is composition in the Endo monoid).
e :: [a -> Maybe a] -> a -> a
e = appEndo . mconcat . map (Endo . totalize)
or even (as suggested below)
e :: Foldable t => t (a -> Maybe a) -> a -> a
e = appEndo . foldMap (Endo . totalize)
Well, you can create a a -> a from a a -> Maybe a:
repair :: (a -> Maybe a) -> a -> a
repair f x = fromMaybe x (f x)
Afterwards, you can just combine (.) and repair:
andThen :: (a -> Maybe a) -> (a -> Maybe a) -> a -> a
andThen f g = repair g . repair f
But there's no library function for that, since there is no general way to get a value out of a Monad.
Are you looking for the maybe monad?
*Main> let f x = a x >>= b >>= c >> return x
*Main> f 1
Just 1
*Main> f 100
Nothing
*Main>
Then if the result is Nothing we can get to your desired end state with fromMaybe (or just maybe and id, same thing):
*Main> let g x = maybe x id (f x)
*Main> g 100
100
When applying the list monad bind function to a simple list and identity function:
[[1,2],[3,4]] >>= \x -> x
I get
[1,2,3,4]
However, the definition of the Monad type class:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
seems to suggest that the function, in my case the lambda function \x -> x, should return a different type to the one passed in. I would expect a compiler error in this case, but I don't have one. I'm running this in ghci.
Why doesn't the compiler throw an error in this case?
The identity function id :: a -> a, or explicitly \x -> x is polymorphic. This means it can be specialized to any type which you construct by substituting some type for a.
In your case (>>= id) the compiler looks at the type of the second argument of
(>>=) :: m c -> (c -> m d) -> m d
and at the type of id and tries to unify them:
a -> a -- id
c -> m d -- the second argument of >>=
this is satisfied in the most general way when we substitute a = m d and c = m d. So the most general type of id inside the expression(>>= id) is
id :: m d -> m d
and the type of the whole expression is
(>>= id) :: (Monad m) => m (m d) -> m d
which is the join function.
a, m and b are type variables and there is nothing that prevents a from being equal to m b in a given situation. That's the idea of polymorphism: if something has type a without any more constraints on a, then it also has type Int, and [[Bool]], and c -> [Int] -> d, and (like here) m b.
So for this specific call, a ~ [Int], b ~ Int, m ~ [], and therefore (>>=)'s type is [[Int]] -> ([Int] -> [Int]) -> [Int].
The inner list is seen as the outer list in the output, but a list is a list nevertheless.
The other way to say this is that
foreach x in [[1,2],[3,4]]:
foreach y in x:
emit y
and
foreach x in [1,2,3,4]:
emit x
are "the same" as regards the emitted elements.
I find the type presentations with lined-up subentities much visually appealing:
(>>=) :: m a -> (a -> m b) -> m b
[[1,2],[3,4]] :: [[Int]] -- actually, (Num a) => [[a]], but never mind that
\x -> x :: a -> a
(>>=) :: m a -> ( a -> m b) -> m b
(>>=) [[1,2],[3,4]] :: ( a -> m b) -> m b m a ~ [[Int]]
(>>=) [[1,2],[3,4]] :: ( a -> [b]) -> [b] m ~ []
(>>=) [[1,2],[3,4]] :: ([Int] -> [b]) -> [b] a ~ [Int]
(>>=) [[1,2],[3,4]] (\ x -> x ) :: [b] [b] ~ [Int]
(>>=) [[1,2],[3,4]] (\ x -> x ) :: [Int] b ~ Int
-- actually, (Num b) => b
Here, it turns out, \ x -> x :: (Num b) => [b] -> [b], not just a -> a.
You see, when ([Int] -> [b]) is matched with the type of (\ x -> x), creating the equivalence of [Int] ~ [b], the [] in [Int] comes from the "inner list", the a in m a; and the [] in [b] comes from the "outer list", the m in m b; but a list is a list, as was said above.
And that's what allows the two list levels to be smashed ("joined") into one — "flattening" a list, or more generally "joining" the two "levels" of a monad into one.
Another way to see it is to expand the monadic code with its specific list version:
[[1,2],[3,4]] >>= \x -> x
=== concatMap id [[1,2],[3,4]] === concat [ x | x <- [[1,2],[3,4]]]
=== concat [id [1,2], id [3,4]] === [ y | x <- [[1,2],[3,4]], y <- x]
=== [1,2,3,4] === [1,2,3,4]
All that matters for f in concatMap f is for it to be a list-producing function: f :: a -> [b].
And concatMap id === concat :: [[a]] -> [a] is a perfectly legal function. Yes, concat is join for the list monad:
ma >>= f === join (fmap f ma) -- or, for lists,
=== concat (map f ma)
=== concatMap f ma -- the definition that we used above
Given ist the Haskell function:
head . filter fst
The question is now how to find the type "manually" by hand. If I let Haskell tell me the type I get:
head . filter fst :: [(Bool, b)] -> (Bool, b)
But I want to understand how this works using only the signatures of the used functions which are defined as follows:
head :: [a] -> a
(.) :: (b -> c) -> (a -> b) -> a -> c
filter :: (a -> Bool) -> [a] -> [a]
fst :: (a, b) -> a
Edit: so many very good explanations ... it's not easy to select the best one!
Types are infered using a process generally called unification.
Haskell belongs to the Hindley-Milner family, which is the unification
algorithm it uses to determine the type of an expression.
If unification fails, then the expression is a type error.
The expression
head . filter fst
passes. Let's do the unification manually to see what why we get
what we get.
Let's start with filter fst:
filter :: (a -> Bool) -> [a] -> [a]
fst :: (a' , b') -> a' -- using a', b' to prevent confusion
filter takes a (a -> Bool), then a [a] to give another [a]. In the expression
filter fst, we pass to filter the argument fst, whose type is (a', b') -> a'.
For this to work, the type fst must unify with the type of filter's first argument:
(a -> Bool) UNIFY? ((a', b') -> a')
The algorithm unifies the two type expressions and tries to bind as many type variables (such as a or a') to actual types (such as Bool).
Only then does filter fst lead to a valid typed expression:
filter fst :: [a] -> [a]
a' is clearly Bool. So the type variable a' resolves to a Bool.
And (a', b') can unify to a. So if a is (a', b') and a' is Bool,
Then a is just (Bool, b').
If we had passed an incompatible argument to filter, such as 42 (a Num),
unification of Num a => a with a -> Bool would have failed as the two expressions
can never unify to a correct type expression.
Coming back to
filter fst :: [a] -> [a]
This is the same a we are talking about, so we substitute in it's place
the result of the previous unification:
filter fst :: [(Bool, b')] -> [(Bool, b')]
The next bit,
head . (filter fst)
Can be written as
(.) head (filter fst)
So take (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
So for unification to succeed,
head :: [a] -> a must unify (b -> c)
filter fst :: [(Bool, b')] -> [(Bool, b')] must unify (a -> b)
From (2) we get that a IS b in the expression
(.) :: (b -> c) -> (a -> b) -> a -> c)`
So the values of the type variables a and c in the
expression (.) head (filter fst) :: a -> c are easy to tell since
(1) gives us the relation between b and c, that: b is a list of c.
And as we know a to be [(Bool, b')], c can only unify to (Bool, b')
So head . filter fst successfully type-checks as that:
head . filter fst :: [(Bool, b')] -> (Bool, b')
UPDATE
It's interesting to see how you can unify starting the process from various points.
I chose filter fst first, then went on to (.) and head but as the other examples
show, unification can be carried out in several ways, not unlike the way a mathematic
proof or a theorem derivation can be done in more than one way!
filter :: (a -> Bool) -> [a] -> [a] takes a function (a -> Bool), a list of the same type a, and also returns a list of that type a.
In your defintion you use filter fst with fst :: (a,b) -> a so the type
filter (fst :: (Bool,b) -> Bool) :: [(Bool,b)] -> [(Bool,b)]
is inferred.
Next, you compose your result [(Bool,b)] with head :: [a] -> a.
(.) :: (b -> c) -> (a -> b) -> a -> c is the composition of two functions, func2 :: (b -> c) and func1 :: (a -> b). In your case, you have
func2 = head :: [ a ] -> a
and
func1 = filter fst :: [(Bool,b)] -> [(Bool,b)]
so head here takes [(Bool,b)] as argument and returns (Bool,b) per definition. In the end you have:
head . filter fst :: [(Bool,b)] -> (Bool,b)
Let's start with (.). It's type signature is
(.) :: (b -> c) -> (a -> b) -> a -> c
which says
"given a function from b to c, and a function from a to b,
and an a, I can give you a b". We want to use that with head and
filter fst, so`:
(.) :: (b -> c) -> (a -> b) -> a -> c
^^^^^^^^ ^^^^^^^^
head filter fst
Now head, which is a function from an array of something to a
single something. So now we know that b is going to be an array,
and c is going to be an element of that array. So for the purpose of
our expression, we can think of (.) as having the signature:
(.) :: ([d] -> d) -> (a -> [d]) -> a -> d -- Equation (1)
^^^^^^^^^^
filter fst
The signature for filter is:
filter :: (e -> Bool) -> [e] -> [e] -- Equation (2)
^^^^^^^^^^^
fst
(Note that I've changed the name of the type variable to avoid confusion
with the as
that we already have!) This says "Given a function from e to a Bool,
and a list of es, I can give you a list of es". The function fst
has the signature:
fst :: (f, g) -> f
says, "given a pair containing an f and a g, I can give you an f".
Comparing this with Equation 2, we know that
e is going to be a pair of values, the first element of
which must be a Bool. So in our expression, we can think of filter
as having the signature:
filter :: ((Bool, g) -> Bool) -> [(Bool, g)] -> [(Bool, g)]
(All I've done here is to replace e with (Bool, g) in Equation 2.)
And the expression filter fst has the type:
filter fst :: [(Bool, g)] -> [(Bool, g)]
Going back to Equation 1, we can see that (a -> [d]) must now be
[(Bool, g)] -> [(Bool, g)], so a must be [(Bool, g)] and d
must be (Bool, g). So in our expression, we can think of (.) as
having the signature:
(.) :: ([(Bool, g)] -> (Bool, g)) -> ([(Bool, g)] -> [(Bool, g)]) -> [(Bool, g)] -> (Bool, g)
To summarise:
(.) :: ([(Bool, g)] -> (Bool, g)) -> ([(Bool, g)] -> [(Bool, g)]) -> [(Bool, g)] -> (Bool, g)
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
head filter fst
head :: [(Bool, g)] -> (Bool, g)
filter fst :: [(Bool, g)] -> [(Bool, g)]
Putting it all together:
head . filter fst :: [(Bool, g)] -> (Bool, g)
Which is equivalent to what you had, except that I've used g as the type variable rather than b.
This probably all sounds very complicated, because I described it in gory detail. However, this sort of reasoning quickly becomes second nature and you can do it in your head.
(skip down for a manual derivation)
Find the type of head . filter fst == ((.) head) (filter fst), given
head :: [a] -> a
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
filter :: (a -> Bool) -> ([a] -> [a])
fst :: (a, b) -> a
This is achieved in a purely mechanical manner by a small Prolog program:
type(head, arrow(list(A) , A)). %% -- known facts
type(compose, arrow(arrow(B, C) , arrow(arrow(A, B), arrow(A, C)))).
type(filter, arrow(arrow(A, bool), arrow(list(A) , list(A)))).
type(fst, arrow(pair(A, B) , A)).
type([F, X], T):- type(F, arrow(A, T)), type(X, A). %% -- application rule
which automagically produces, when run in a Prolog interpreter,
3 ?- type([[compose, head], [filter, fst]], T).
T = arrow(list(pair(bool, A)), pair(bool, A)) %% -- [(Bool,a)] -> (Bool,a)
where types are represented as compound data terms, in a purely syntactical manner. E.g. the type [a] -> a is represented by arrow(list(A), A), with possible Haskell equivalent Arrow (List (Logvar "a")) (Logvar "a"), given the appropriate data definitions.
Only one inference rule, that of an application, was used, as well as Prolog's structural unification whereby compound terms match if they have the same shape and their constituents match: f(a1, a2, ... an) and g(b1, b2, ... bm) match iff f is the same as g, n == m and ai matches bi, with logical variables being able to take on any value as needed, but only once (can't be changed).
4 ?- type([compose, head], T1). %% -- (.) head :: (a -> [b]) -> (a -> b)
T1 = arrow(arrow(A, list(B)), arrow(A, B))
5 ?- type([filter, fst], T2). %% -- filter fst :: [(Bool,a)] -> [(Bool,a)]
T2 = arrow(list(pair(bool, A)), list(pair(bool, A)))
To perform type inference manually in a mechanical fashion, involves writing things one under another, noting equivalences on the side and performing the substitutions thus mimicking the operations of Prolog. We can treat any ->, (_,_), [] etc. purely as syntactical markers, without understanding their meaning at all, and perform the process mechanically using structural unification and, here, only one rule of type inference, viz. rule of application: (a -> b) c ⊢ b {a ~ c} (replace a juxtaposition of (a -> b) and c, with b, under the equivalence of a and c). It is important to rename logical variables, consistently, to avoid name clashes:
(.) :: (b -> c ) -> ((a -> b ) -> (a -> c )) b ~ [a1],
head :: [a1] -> a1 c ~ a1
(.) head :: (a ->[a1]) -> (a -> c )
(a ->[c] ) -> (a -> c )
---------------------------------------------------------
filter :: ( a -> Bool) -> ([a] -> [a]) a ~ (a1,b),
fst :: (a1, b) -> a1 Bool ~ a1
filter fst :: [(a1,b)] -> [(a1,b)]
[(Bool,b)] -> [(Bool,b)]
---------------------------------------------------------
(.) head :: ( a -> [ c ]) -> (a -> c) a ~ [(Bool,b)]
filter fst :: [(Bool,b)] -> [(Bool,b)] c ~ (Bool,b)
((.) head) (filter fst) :: a -> c
[(Bool,b)] -> (Bool,b)
You can do this the "technical" way, with lots of complicated unification steps. Or you can do it the "intuitive" way, just looking at the thing and thinking "OK, what have I got here? What is this expecting?" and so on.
Well, filter expects a function and a list, and returns a list. filter fst specifies a function, but there's no list given - so we're still waiting for the list input. So filter fst is taking a list and returning another list. (This is quite a common Haskell phrase, by the way.)
Next, the . operator "pipes" the output to head, which expects a list and returns one of the elements from that list. (The first one, as it happens.) So whatever filter comes up with, head gives you the first element of it. At this point, we can conclude
head . filter foobar :: [x] -> x
But what is x? Well, filter fst applies fst to every element of the list (to decide whether to keep it or throw it). So fst must be applicable to the list elements. And fst expects a 2-element tuple, and returns the first element of that tuple. Now filter is expecting fst to return a Bool, so that means the first element of the tuple must be a Bool.
Putting all that together, we conclude
head . filter fst :: [(Bool, y)] -> (Bool, y)
What is y? We don't know. We don't actually care! The above functions will work whatever it is. So that's our type signature.
In more complicated examples it can be harder to figure out what's going on. (Especially when weird class instances get involved!) But for smallish ones like this, involving common functions, you can usually just think "OK, what goes in here? What comes out there? What does this function expect?" and walk right up to the answer without too much manual algorithm-chasing.
I need to run a function that takes two arguments several times. I have two lists containing these arguments and I'd like to be able to use map or something similar to call the function with the corresponding args.
The function I want to call has this type:
runParseTest :: String -> String -> IO()
The lists are created like this:
-- Get list of files in libraries directory
files <- getDirectoryContents "tests/libraries"
-- Filter out ".." and "." and add path
let names = filter (\x -> head x /= '.') files
let libs = ["tests/libraries/" ++ f | f <- names]
So lets say that names contains ["test1.js", "test2.js", "test3.js"] and libs contains ["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
I know I could create a helper function that does this fairly easily, but out of interest, is it possible to do in one line using map?
This is what I have so far, but obviously the first argument is always "test":
mapM_ (runParseTest "test") libs
I apologise if this is unclear. I can provide more info if necessary.
This is a great time to use Hoogle! Hoogle is a search engine for searching Haskell types. For instance, a Hoogle query for (a -> b) -> [a] -> [b] pulls up map. Here, you have a function of type String -> String -> IO (); you want a function of type (String -> String -> IO ()) -> [String] -> [String] -> IO (). Hoogle can often generalize by itself, but it's having trouble here, so let's help it out: You just want (a -> a -> IO ()) -> [a] -> [a] -> IO () for any a. If you Hoogle for that type signature, the first result is zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m () in the Control.Monad module, which does exactly what you want. This is part of a family of functions, with varying degrees of generality:
zip :: [a] -> [b] -> [(a,b)], which pairs up two lists, truncating the shorter one.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c], which runs a supplied function on elements from each of the two lists; zip = zipWith (,).
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c], which is like zipWith inside a monad; zipWithM f xs ys = sequence $ zipWith f xs ys.
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m (), which is like zipWithM but discards its result; zipWithM_ f xs ys = zipWithM f xs ys >> return () = sequence_ $ zipWith f xs ys.
zip3 :: [a] -> [b] -> [c] -> [(a, b, c)], whose functionality I'm sure you can figure out :-)
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d], which is like zipWith on three lists; zipWith3 = zip (,,).
A family of zipN and zipWithN functions in Data.List, going up through zip7/zipWith7. (Arguably, this starts with id :: [a] -> [a] as zip1 and map :: (a -> b) -> [a] -> [b] as zipWith1, which is where your question comes from.)
And, in greatest generality, the ZipList applicative functor. Given some lists xs1…xsN, then runZipList $ f <$> ZipList xs1 <*> ZipList xs2 <*> ... <*> ZipList xsN = runZipList $ liftAN f (ZipList xs1) ... (ZipList xsN) behaves just like zipWithN f xs1 ... xsN.
So, in your specific use case, we're going to have—with a few extra changes—the following:
import Data.List (isPrefixOf)
...
-- I got rid of `head` because it's a partial function, and I prefer `map` to
-- list comprehensions for simple things
do files <- getDirectoryContents "tests/libraries"
let names = filter (not . ("." `isPrefixOf`)) files
libs = map ("tests/libraries/" ++) names
zipWithM_ runParseTest names libs
So lets say that names contains ["test1.js", "test2.js", "test3.js"]
and libs contains ["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
It's possible to do that with zip:
map (\(a,b) -> runParseTest a b) $ zip names libs
Or maybe uncurry runParseTest:
map (uncurry runParseTest) $ zip names libs
Or with zipWith:
zipWith runParseTest names libs
And like Ozgur said, there are some analogues for monads:
> :t zipWithM
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
> :t zipWithM_
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
You are looking for zipWithM_.
You say you could write a helper function which does this. Which means you know the type of the function you are looking for. In such cases you can use hoogle.
(Try: Monad m => [a] -> [b] -> m ())
While waiting for answers I created a solution of my own with a new function called map2M_ based on the source code for map and mapM_:
map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
map2 _ [] _ = []
map2 _ _ [] = []
map2 f (a:as) (b:bs) = f a b : map2 f as bs
map2M_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
map2M_ f as bs = sequence_ (map2 f as bs)