Newbie Q: composeMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)

I am trying to solve a problem from "The Craft of Functional Programming" book: 14.38 ... define the function: data Maybe a = Nothing | Just a composeMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c) using functions: squashMaybe :: Maybe (Maybe a) -> Maybe a squashMaybe (Just (Just x)) = Just x squashMaybe _ = Nothing mapMaybe :: (a -> b) -> Maybe a -> Maybe b mapMaybe f Nothing = Nothing mapMaybe f (Just x) = Just (f x) As a first step to the solution I defined auxilary function: f1 f g x = mapMaybe f (g x) GHCi gives the following type for this function: f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b ^^^ Q: I don't quite understand this signature. I would expect this instead (by mapMaybe definition): f1 :: (a -> b) -> (t -> Maybe a) -> Maybe b
From where does the second 't' come from? What are the arguments and what f1 returns in this case?

Hi Dmitri, your f1 function has 3 arguments, f, g and x. you pass f as the first argument to mapMaybe, so it naturally must have type (a -> b). you pass the result of (g x) to the second argument of mapMaybe, so (g x) must have type Maybe a. This means g must have the type (t -> Maybe a) where t is the type of x. This gives f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b you are going to be passing in something with type (c -> Maybe d) as the first argument to f1. (I used different type variables to reduce confusion) This constraint gives f1 the following type f1 :: (c -> Maybe d) -> (t -> Maybe c) -> t -> Maybe (Maybe d) substituting different type variable names gives f1 :: (b -> Maybe c) -> (a -> Maybe b) -> a -> Maybe (Maybe c) So you are very close to finishing... :) Hope this helps. DeeJay Dmitri O.Kondratiev wrote:
I am trying to solve a problem from "The Craft of Functional Programming" book:
14.38 ... define the function: data Maybe a = Nothing | Just a composeMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
using functions:
squashMaybe :: Maybe (Maybe a) -> Maybe a squashMaybe (Just (Just x)) = Just x squashMaybe _ = Nothing
mapMaybe :: (a -> b) -> Maybe a -> Maybe b mapMaybe f Nothing = Nothing mapMaybe f (Just x) = Just (f x)
As a first step to the solution I defined auxilary function: f1 f g x = mapMaybe f (g x)
GHCi gives the following type for this function:
f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b ^^^ Q: I don't quite understand this signature. I would expect this instead (by mapMaybe definition): f1 :: (a -> b) -> (t -> Maybe a) -> Maybe b
From where does the second 't' come from? What are the arguments and
what f1 returns in this case? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hey DeeJay,
Thanks for detailed answer, it really helps as it shows the way I need
to follow!
It also helped me to realize that my question why
f1 f g x = mapMaybe f (g x)
has this type:
f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b
and not that (type which I expected):
f1 :: (a -> b) -> (t -> Maybe a) -> Maybe b
was actually very stupid of me, as I just blindly missed that f1 *also
has* a third parameter 'x' of type 't' !!!
(Perhaps that happened to me because I was too much absorbed by the
grave nature of the problem of composing functions returning 'Maybe'
:)
Thanks again!
Dima
On 11/8/06, DeeJay-G615
Hi Dmitri,
your f1 function has 3 arguments, f, g and x.
you pass f as the first argument to mapMaybe, so it naturally must have type (a -> b). you pass the result of (g x) to the second argument of mapMaybe, so (g x) must have type Maybe a. This means g must have the type (t -> Maybe a) where t is the type of x.
This gives f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b
you are going to be passing in something with type (c -> Maybe d) as the first argument to f1. (I used different type variables to reduce confusion)
This constraint gives f1 the following type
f1 :: (c -> Maybe d) -> (t -> Maybe c) -> t -> Maybe (Maybe d)
substituting different type variable names gives
f1 :: (b -> Maybe c) -> (a -> Maybe b) -> a -> Maybe (Maybe c)
So you are very close to finishing... :) Hope this helps.
DeeJay
Dmitri O.Kondratiev wrote:
I am trying to solve a problem from "The Craft of Functional Programming" book:
14.38 ... define the function: data Maybe a = Nothing | Just a composeMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
using functions:
squashMaybe :: Maybe (Maybe a) -> Maybe a squashMaybe (Just (Just x)) = Just x squashMaybe _ = Nothing
mapMaybe :: (a -> b) -> Maybe a -> Maybe b mapMaybe f Nothing = Nothing mapMaybe f (Just x) = Just (f x)
As a first step to the solution I defined auxilary function: f1 f g x = mapMaybe f (g x)
GHCi gives the following type for this function:
f1 :: (a -> b) -> (t -> Maybe a) -> t -> Maybe b ^^^ Q: I don't quite understand this signature. I would expect this instead (by mapMaybe definition): f1 :: (a -> b) -> (t -> Maybe a) -> Maybe b
From where does the second 't' come from? What are the arguments and
what f1 returns in this case? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Dmitri O Kondratiev, dokondr@gmail.com http://www.geocities.com/dkondr/
participants (2)
-
DeeJay-G615
-
Dmitri O.Kondratiev