I am currently in need of a bit of brain training and I found this article on Haskell and Monads
I'm having trouble with exercise 7 re. Randomised function bind.
To make the problem even simpler to experiment, I replaced the StdGen
type with an unspecified type. So instead of...
bind :: (a -> StdGen -> (b,StdGen)) -> (StdGen -> (a,StdGen)) -> (StdGen -> (b,StdGen))
I used...
bind :: (a -> c -> (b,c)) -> (c -> (a,c)) -> (c -> (b,c))
and for the actual function impelemtation (just straight from the exercise)
bind f x seed = let (x',seed') = x seed
in f x' seed'
and also 2 randomised functions to trial with:
rndf1 :: (Num a, Num b) => a -> b -> (a,b)
rndf1 a s = (a+1,s+1)
rndf2 :: (Num a, Num b) => a -> b -> (a,b)
rndf2 a s = (a+8,s+2)
So with this in a Haskell compiler (ghci), I get...
:t bind rndf2
bind rndf2 :: (Num a, Num c) => (c -> (a, c)) -> c -> (a, c)
This matches the bind curried with rndf2
as the first parameter.
But the thing I don't understand is how...
:t bind rndf2 . rndf1
Suddenly gives
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
This is the correct type of the composition that we are trying to produce because
bind rndf2 . rndf1
Is a function that:
- takes the same parameter type(s) as
rndf1
- AND takes the return from
rndf1
and pipes it as an input ofrndf2
to return the same type asrndf2
rndf1
can take 2 parameters a -> c
and rndf2
returns (a, c)
so it matches that a composition of these function should have type:
bind rndf2 . rndf1 :: (Num a, Num c) => a -> c -> (a, c)
This does not match the naive type that I initially came up with for bind
bind f :: (a -> b -> (c, d)) -> (c, d) -> (e, f)
Here bind
mythically takes a function that takes two parameters and produces a function that takes a tuple in order that the output from rndf1
can be fed into rndf2
- why the bind function needs to be coded as it is
- Why the bind function does not have the naive type
unit
, then it's wrong becauseunit :: a -> c -> (a,c)
(note the missingNum
contexts). – Vitus