繁体   English   中英

手动推导有趣的类型xss = \\ f->让ope xy = x。 F 。 文件夹1中的y

[英]Manually deriving the type of fun xss = \f -> let ope x y = x . f . y in foldr1 ope xss

我正在尝试手动得出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 fun xss = \\f -> let ope xy = x . f . y in foldr1 ope xss

F 。 ÿ

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->让ope xy = x。 F 。 ÿ

(.) (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

然后a ~ (b2 -> c2), a ~ (a2 -> b1), a ~ (b1 -> b2) and t4 ~ [a]似乎是错误的。

有什么帮助吗?

谢谢,
塞巴斯蒂安。

从功能开始

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

因此,我们从foldr1开始:

foldr1 :: (a -> a -> a) -> [a] -> a

这样我们就可以分解

foldrl1
    ope    -- (a -> a -> a)
    xss    -- [a]

所以ope :: a -> a -> a ,这真的很有用,因为它将xy的类型简化为完全限制为a ,或者换句话说,它们都具有相同的类型。 由于它们都是函数(按.要求),因此不必长久地统一它们的类型,我只是说x, y :: b -> c

ope x y =    x     .    f     .    y
--        (b -> c) . (s -> t) . (b -> c)

我现在将f的类型保留为unknowns,除了指定它必须是一个函数之外。 因为我们知道xy具有相同的类型,所以我们现在可以说y的输出类型与f的输入类型相同,因此s ~ c ,并且f的输出类型必须与x相同的输入类型,所以t ~ b ,所以我们得到

ope x y =    x     .    f     .    y
--        (b -> c) . (c -> b) . (b -> c)

现在,我们可以填写fun的签名了。 我们已经知道xss的类型,它是foldr1 a ~ b -> c ,并且由于foldr1的输出类型也是a ,我们得到

 fun :: [b -> c] -> (c -> b) -> (b -> c)

实际上,这就是GHCi给我们的类型

这是推导。

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)

函数组成是关联的: f . (g . h) f . (g . h) =〜= (f . g) . h (f . g) . h 这就是为什么表达式f . g . h f . g . h f . g . h格式正确。

就像(.) :: (b->c) -> (a->b) -> (a->c)创建了一个由两个函数组成的链,两个函数相互馈送,即f . g . h f . g . h f . g . h表达式创建一个由三个函数组成的链,每个函数都将其前任的输出作为输入。

有时使用(.)的表亲>>>会更容易,它只会翻转参数的顺序:

f . g === g >>> f

它在Control.Category定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM