I'm trying to manually derive the type of fun xss = \\f -> let ope xy = x . f . y in foldr1 ope xss
fun xss = \\f -> let ope xy = x . f . y in foldr1 ope xss
f . y
y :: t1 -- First occurrence
f :: t2 -- First occurrence
(.) (b1 -> c1) -> (a1 -> b1) -> a1 -> c1 -- (.) definition
t1 ~ a1 -> b1 -- y unified with (a1 -> b1)
t2 ~ b1 -> c1 -- y unified with (b1 -> c1)
y :: a1 -> b1
f :: b1 -> c1
---
f . y :: a1 -> c1 -- Cancellation rule
\\f -> let ope xy = x . f . y
(.) (b2 -> c2) -> (a2 -> b2) -> a2 -> c2 -- (.) definition
x :: t3 -- First occurrence
t3 ~ b2 -> c2 -- x unified with (b2 -> c2)
a1 -> c1 ~ a2 -> b2 -- f . y unified with (a2 -> b2)
a1 ~ a2
c1 ~ b2
y :: a2 -> b1 -- Substituing a1 by a2
f :: b1 -> b2 -- Substituing c1 by b2
x :: b2 -> c2 -- Substituing t3 by b2 -> c2
---
x . f . y :: a2 -> c2 -- Cancellation rule
(\f -> let ope x y :: x . f . y)
:: (b2 -> c2) -> (a2 -> b1) -> (b1 -> b2) -> a2 -> c2 -- Adding f
foldr1 ope xss
foldr1 :: (a -> a -> a) -> [a] -> a -- foldr1 definition
xss ~ t4 -- First occurrence
Then a ~ (b2 -> c2), a ~ (a2 -> b1), a ~ (b1 -> b2) and t4 ~ [a]
which seems to be an error.
Any help?
Thanks,
Sebastián.
To start with the function
fun xss = \f -> let ope x y = x . f . y in foldr1 ope xss
I'll rewrite this as
fun xss f = foldr1 ope xss
where ope x y = x . f . y
So we start with foldr1
:
foldr1 :: (a -> a -> a) -> [a] -> a
So we can break down
foldrl1
ope -- (a -> a -> a)
xss -- [a]
So ope :: a -> a -> a
, this is really useful to know since it simplifies the types of x
and y
to be restricted entirely to a
, or put another way they both have the same type. Since they're both functions (as required by .
), instead of unifying their types the long way I'll just say that x, y :: b -> c
ope x y = x . f . y
-- (b -> c) . (s -> t) . (b -> c)
I've left f
's type as unknowns right now, other than specifying that it has to be a function. Since we know that x
and y
have the same type, we can now say that y
's output type is the same as f
's input type, so s ~ c
, and f
's output type has to be the same as x
's input type, so t ~ b
, so we get
ope x y = x . f . y
-- (b -> c) . (c -> b) . (b -> c)
So now we can fill fun
's signature. We already know the type of xss
, it's a ~ b -> c
, and since foldr1
's output type is also a
, we get
fun :: [b -> c] -> (c -> b) -> (b -> c)
And indeed this is the type that GHCi
gives us
Here's the derivation.
fun xss = \f -> let ope x y = x . f . y in foldr1 ope xss
fun xss f = foldr1 ope xss
where
ope x y = x . f . y y :: a -> b
= y >>> f >>> x f :: b -> c
a -> b b -> c c -> d x :: c -> d
:: a -------------------> d
ope x y :: a->d
ope :: (c->d) -> (a->b) -> (a->d)
foldr1 :: ( a1 -> a1 -> a1 ) -> [ a1 ] -> a1 c ~ a, d ~ b
((a->b) -> (a->b) -> (a->b)) -> [a->b] -> (a->b) a1 ~ a->b
foldr1 ope xss :: (a->b)
fun xss f :: a->b
fun :: [a->b] -> (b->a) -> (a->b)
Function composition is associative: f . (g . h)
f . (g . h)
=~= (f . g) . h
(f . g) . h
. That's why the expression f . g . h
f . g . h
f . g . h
is well formed.
Just as (.) :: (b->c) -> (a->b) -> (a->c)
creates a chain of two functions feeding one from another, the f . g . h
f . g . h
f . g . h
expression creates a chain of three functions, each taking as input its predecessor's output.
It is sometimes easier to use (.)
's cousin, >>>
, which just flips the order of arguments:
f . g === g >>> f
It is defined in Control.Category
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.