在Haskell函数中键入量词

时间:2017-02-27 11:48:48

标签: haskell lambda-calculus

假设我有两个以下类型的Haskell函数,并激活了ExplicitForAll,

f :: forall a. (a -> Int)
g :: forall a. (Int -> a)

在我看来,g的类型与Int -> (forall a. a)同构,因为例如g(2)的类型为forall a. a

但是,f的类型与(forall a. a) -> Int看起来并不相同。 f是一个多态函数,它知道在每个输入类型a上计算什么,在数学中我想它宁可是一族函数;但我不认为它可以处理一个包含所有类型的单个参数。

类型化lambda演算的规则是类型量词分布在函数目标类型上,而不是函数源类型吗?

Haskell中是否存在类型(forall a. a) -> Int,可能限制为类型类(forall a. SomeClass a => a) -> Int?它有用吗?

3 个答案:

答案 0 :(得分:2)

weird :: (forall a. a) -> Int是不必要的具体。

undefined是唯一具有forall a. a类型的值,因此定义必须为weird _ = someInteger,这只是const的限制性更强的版本。

答案 1 :(得分:2)

∀ a .基本上只是一个额外的隐式参数,或者更确切地说,应该处理与该参数有关的类型约束的规范。例如,

f :: ∀ a . Show a => (a -> Int)
g :: ∀ a . Show a => (Int -> a)

本质上是两个参数的函数,

f' :: ShowDictionary a -> a -> Int
g' :: ShowDictionary a -> Int -> a

甚至是笨蛋,

type GenericReference = Ptr Foreign.C.Types.Void -- this doesn't actually exist

f'' :: (GenericReference -> String) -> GenericReference -> Int
g'' :: (GenericReference -> String) -> Int -> GenericReference

现在,这些只是单态(或弱动态类型)函数。我们可以清楚地使用flip来获取

f''' :: GenericReference -> (GenericReference -> String) -> Int
g''' :: Int -> (GenericReference -> String) -> GenericReference

后者可以使用任何Int参数进行部分评估,因此g确实等同于γ :: Int -> (∀ a . Show a => Int -> a)

使用f''',将它应用于一些无效指针参数将是灾难的一个方法,因为类型系统无法确保实际传递的类型与{{{ 1}}函数准备处理。

答案 2 :(得分:0)

这是Chi上述评论的副本,它通过将函数解释为逻辑含义(Curry-Howard对应)来解释理论部分:

  

类型量子可以用箭头交换,如逻辑:   命题p -> forall a. q(a)相当于forall a. p -> q(a)   提供的p不依赖于a。如果Haskell有存在类型,我们   会有同构(forall a. p(a) -> q) ~ ((exists a. p(a)) -> q)。它也与产品通勤(forall a. p a, forall a. q a) ~ forall a. (p a, q a)。总而言之,它更棘手。

我还链接了RankNTypes的规范。它确实强制执行“浮出”类型量词的规则,并定义类型(forall a. SomeClass a => a) -> Int