是什么使Haskell中的两个类型表达式等效?

时间:2018-11-05 18:24:53

标签: haskell types equivalence

所以有人问我,这3种类型表达式在Haskell中是否等效:

τ1 = (a -> a) -> (a -> a -> a)
τ2 = a -> a -> ((a -> a) -> a)
τ3 = a -> a -> (a -> (a -> a))

如果我删除了括号,我将留下这个

τ1 = (a -> a) -> a -> a -> a
τ2 = a -> a -> (a -> a) -> a
τ3 = a -> a -> a -> a -> a

因此,对我来说,显而易见的是,它们彼此都是不同的。但是,根据问题,这两个答案是错误的:

τ1 !≡ τ2 !≡ τ3 !≡ τ1
τ1 !≡ τ2 ≡ τ3

所以我有点困惑,什么是正确的答案,为什么?

3 个答案:

答案 0 :(得分:6)

实际上,由于您提到的原因,它们都是不同的。

我们甚至可以要求GHC进行确认。 (下面,我选择a ~ Int以获得封闭类型。)

> import Data.Type.Equality
> type T1 a = (a -> a) -> (a -> a -> a)
> type T2 a = a -> a -> ((a -> a) -> a)
> type T3 a = a -> a -> (a -> (a -> a))
> :kind! T1 Int == T2 Int
T1 Int == T2 Int :: Bool
= 'False
> :kind! T1 Int == T3 Int
T1 Int == T3 Int :: Bool
= 'False
> :kind! T2 Int == T3 Int
T2 Int == T3 Int :: Bool
= 'False

答案 1 :(得分:5)

这三种类型...

type T1 a = (a -> a) -> (a -> a -> a)
type T2 a = a -> a -> ((a -> a) -> a)
type T3 a = a -> a -> (a -> (a -> a))

...确实是截然不同的。但是,T1T2在它们之间存在同构的意义上是等价的,这等同于更改参数的顺序:

GHCi> :info T1
type T1 a = (a -> a) -> a -> a -> a
    -- Defined at <interactive>:12:1
GHCi> :info T2
type T2 a = a -> a -> (a -> a) -> a
    -- Defined at <interactive>:13:1
GHCi> :t flip
flip :: (a -> b -> c) -> b -> a -> c
GHCi> :t (flip .)
(flip .) :: (a1 -> a2 -> b -> c) -> a1 -> b -> a2 -> c
GHCi> f = (flip .) . flip
GHCi> :t f :: T1 a -> T2 a
f :: T1 a -> T2 a :: T1 a -> T2 a
GHCi> g = flip . (flip .)
GHCi> :t g :: T2 a -> T1 a
g :: T2 a -> T1 a :: T2 a -> T1 a

然后我们可以证明fg是反数(即g . f = idf . g = id):

f . g
(flip .) . flip . flip . (flip .)
(flip .) . (flip .) -- flip . flip = id
id -- (flip .) . (flip .) = \h -> \x -> flip (flip (h x)) = \h -> \x -> h x = id

g . f
flip . (flip .) . (flip .) . flip
flip . flip 
id

答案 2 :(得分:3)

我同意您的评估。这三种类型都不相同,您已正确简化了它们。如果您认为所提供的答案与您的不同,您确定阅读的问题是正确的吗?