I\'m trying to understand why the type of fun g x = ys where ys = [x] ++ filter (curry g x) ys
is ((a, a) -> Bool) -> a -> [a]
.
I
We can derive types in Haskell in a more or less mechanical manner, using the general scheme of
foo x = y -- is the same as
foo = \x -> y -- so the types are
foo :: a -> b , x :: a , y :: b -- so that
foo x :: b
which means that e.g.
f x y z :: d , x :: a , y :: b, z :: c
entails
f x y :: c -> d
f x :: b -> c -> d
f :: a -> b -> c -> d
etc. With these simple tricks type derivation will become trivial for you. Here, with
filter :: (a -> Bool) -> [a] -> [a]
curry :: ((a, b) -> c) -> a -> b -> c
(++) :: [a] -> [a] -> [a]
we simply write down the stuff carefully lined up, processing it in a top-down manner, consistently renaming and substituting the type variables, and recording the type equivalences on the side:
fun g x = ys where ys = [x] ++ filter (curry g x) ys
fun g x :: c , ys :: c
fun g :: b -> c , x :: b
fun :: a -> b -> c , g :: a
ys = [x] ++ filter (curry g x) ys c ~ c (++) [x] (filter (curry g x) ys) :: c (++) :: [a1] -> [a1] -> [a1] ----------------------------------------------- (++) :: [b] -> [b] -> [b] , a1 ~ b , c ~ [b] filter (curry g x ) ys :: [b] filter :: (a2 -> Bool) -> [a2] -> [a2] , a2 ~ b -------------------------------------- filter :: (b -> Bool) -> [b] -> [b] curry g x :: b -> Bool curry :: ((a3, b) -> c3 ) -> a3 -> b -> c3 , c3 ~ Bool , a3 ~ b ------------------------------------------- curry :: ((b , b) -> Bool) -> b -> b -> Bool , a ~ ((b,b) -> Bool)
so we have that a ~ ((b,b) -> Bool)
and c ~ [b]
, and thus
fun :: a -> b -> c
fun :: ((b,b) -> Bool) -> b -> [b]
which is the same as ((a,a) -> Bool) -> a -> [a]
, up to a consistent renaming of type variables.