The following equations are written in Miranda Syntax, but due to the similarities between Miranda and Haskell I expect Haskell programmers should understand it!
If you define the following functions:
rc v g i = g (v:i)
rn x = x
rh g = hd (g [])
f [] y = y
f (x:xs) y = f xs (rc x y)
g [] y = y
g (x:xs) y = g xs (x:y)
How do you work out the type of the functions? I think I understand how to work it out for f,g and rn but I'm confused about the partial application part.
rn is going to be * -> * (or anything -> anything, I think it's a -> a in Haskell?)
For f and g, are the function types both [*] -> * -> *?
I'm unsure how to approach finding the types for rc and rh though. In rc, g is being partially applied to the variable i - so I'm guessing that this constrains the type of i to be [*]. What order are rc and g applied in the definition of rc? Is g applied to i, and then the resulting function used as the argument for rc? Or does rc take 3 separate parameters of v,g and i? I'm really confused.. any help would be appreciated! Thanks guys.
Sorry forgot to add that hd is the standard head function for a list and is defined as:
hd :: [*] -> *
hd (a:x) = a
hd [] = error "hd []"
The type is inferred from what is already known of types and how expressions are used in the definition.
Let's begin at the top,
rc v g i = g (v : i)
so rc :: a -> b -> c -> d
and we must see what can be found out about a, b, c
and d
. On the right hand side, there appears (v : i)
, so with v :: a
, we see that i :: [a]
, c = [a]
. Then g
is applied to v : i
, so g :: [a] -> d
, altogether,
rc :: a -> ([a] -> d) -> [a] -> d
rn x = x
means that there's no constraint on the argument type of rn
and its return type is the same, rn :: a -> a
.
rh g = hd (g [])
Since rh
's argument g
is applied to an empty list on the RHS, it must have type [a] -> b
, possibly more information about a
or b
follows. Indeed, g []
is the argument of hd
on the RHS, so g [] :: [c]
and g :: [a] -> [c]
, hence
rh :: ([a] -> [c]) -> c
Next
f [] y = y
f (x:xs) y = f xs (rc x y)
The first argument is a list, and if that is empty, the result is the second argument, so f :: [a] -> b -> b
follows from the first equation. Now, in the second equation, on the RHS, the second argument to f
is rc x y
, hence rc x y
must have the same type as y
, we called that b
. But
rc :: a -> ([a] -> d) -> [a] -> d
, so b = [a] -> d
. Hence
f :: [a] -> ([a] -> d) -> [a] -> d
Finally
g [] y = y
g (x:xs) y = g xs (x:y)
from the first equation we deduce g :: [a] -> b -> b
. From the second, we deduce b = [a]
, since we take the head of g
's first argument and cons it to the second, thus
g :: [a] -> [a] -> [a]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With