混淆替代类型

时间:2017-09-06 09:07:00

标签: haskell

我正在努力了解类型替换的工作原理。

请考虑以下示例:

*Lib Lib> :t id (*)
id (*) :: Num a => a -> a -> a

让我们看看id(*)的类型签名:

*Lib Lib> :t (*)
(*) :: Num a => a -> a -> a

*Lib Lib> :t id
id :: a -> a

如何在没有前奏曲的情况下替换id (*)的类型:

id  :: a -> a

(*) :: a -> ( a -> a ) "I did parentheses because of currying.

a的第一个id,将通过a -> ( a -> a )替代

 id  :: |a          | -> a
 (*) :: |a -> a -> a| 

因为a也是id的结果类型(标识为-> a),因此id的类型变为a -> a -> a

现在考虑更复杂的例子,我将如何进行替换:

*Lib Lib> :t (+) . (*)

.函数的类型签名:

*Lib Lib> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

现在让我们用(+)代替第一个参数:

(.) :: (+)
(.) :: (b ->|c)      -> (a -> b) -> a -> c
(.) :: (a ->|a -> a) -> (a -> b) -> a -> c

让我们用(*)代替第二个参数:

(.) :: (+)           -> (*)    
(.) :: (b ->|c)      -> (a ->|b)      -> a -> c
(.) :: (a ->|a -> a) -> (a ->|a -> a) -> a -> c

然后逐步替换,直到我们得到最终类型:

(.) :: (b ->|c)      -> (a ->|b)      -> a -> c
(.) :: (a ->|a -> a) -> (a ->|a -> a) -> a -> c 

"the b on the first argument becomes to (a -> a), because
"of the substitution of the final type of second argument 
(.) :: (b        ->|c     ) -> (a ->|b)      -> a -> c
(.) :: ((a -> a) ->|a -> a) -> (a ->|a -> a) -> a -> c 

"the c, the final type becomes (a -> a), because the result
"type of the first argument
(.) :: (b        ->|c     ) -> (a ->|b)      -> a -> c
(.) :: ((a -> a) ->|a -> a) -> (a ->|a -> a) -> a -> a -> a

等等,我上面提到的最终类型是错误的

(+) . (*) :: a -> a -> a

正确的类型是:

*Lib> :t (+) . (*)
(+) . (*) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a

我的问题是,为什么我得到(a -> a),合成结尾没有类型参数b

为了澄清,我的意思是,让我们将最终的类型参数与函数组合的签名进行比较:

(.) :: (b -> c) -> (a -> b) -> a ->          -> c
                               a -> (a -> a) -> a -> a

我可以看到,ac之间存在漏洞,因为(a -> a)b的类型。 为什么类型参数b突然出现在ac之间?

我希望这个解释是可以理解的。

0 个答案:

没有答案