作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
下面描述的所有实验都是用 GHC 8.0.1 完成的。
这个问题是 RankNTypes with type aliases confusion 的后续问题。 .那里的问题归结为像这样的函数类型......
{-# LANGUAGE RankNTypes #-}
sleight1 :: a -> (Num a => [a]) -> a
sleight1 x (y:_) = x + y
ThinAir.hs:4:13: error:
* No instance for (Num a) arising from a pattern
Possible fix:
add (Num a) to the context of
the type signature for:
sleight1 :: a -> (Num a => [a]) -> a
* In the pattern: y : _
In an equation for `sleight1': sleight1 x (y : _) = x + y
Num a
cannot be moved outside of the type of the second argument (如果我们有
a -> a -> (Num a => [a])
则可能)。既然如此,我们最终会尝试将更高级别的约束添加到已经在整个事物上量化的变量,即:
sleight1 :: forall a. a -> (Num a => [a]) -> a
(+)
不需要
Num
的东西,并将有问题的参数的类型与结果的类型分离:
sleight2 :: a -> (Num b => b) -> a
sleight2 x y = const x y
ThinAir.hs:7:24: error:
* No instance for (Num b) arising from a use of `y'
Possible fix:
add (Num b) to the context of
the type signature for:
sleight2 :: a -> (Num b => b) -> a
* In the second argument of `const', namely `y'
In the expression: const x y
In an equation for `sleight2': sleight2 x y = const x y
Failed, modules loaded: none.
const
然而,这里可能是不必要的,所以我们可以尝试自己编写实现:
sleight3 :: a -> (Num b => b) -> a
sleight3 x y = x
Prelude> :r
[1 of 1] Compiling Main ( ThinAir.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t sleight3
sleight3 :: a -> (Num b => b) -> a
*Main> sleight3 1 2
1
Num
对第二个参数的约束:
*Main> sleight3 1 "wat"
1
undefined
只要我们从不评估它,一个不可满足的约束就可以很好地保留在一个类型中,只要它不用于右侧任何地方的统一。然而,这感觉像是一个非常弱的类比,特别是考虑到我们通常理解的非严格性是一个涉及值而不是类型的概念。此外,这让我们离掌握世界如何
String
更近了一步。与
Num b => b
合并——假设这样的事情真的发生了,我完全不确定。那么,当约束似乎以这种方式消失时,对正在发生的事情的准确描述是什么?
最佳答案
哦,它变得更加奇怪:
Prelude> sleight3 1 ("wat"+"man")
1
Prelude Data.Void> sleight3 1 (37 :: Void)
1
Num
对该论点的约束。只是,因为(正如 chi 已经评论过的)
b
处于协变位置,这不是您在调用
sleight3
时必须提供的约束.相反,您可以选择任何类型
b
,然后不管它是什么,
sleight3
将提供
Num
以它为例!
sleight3
不能为字符串提供这样的 num 实例,而且绝对不能为
Void
.但它实际上也不需要,因为就像你说的那样,该约束将适用的论点从未被评估过。回想一下,受约束的多态值本质上只是字典参数的函数。
sleight3
只是 promise 在实际使用之前提供这样的字典
y
, 但随后它不使用
y
无论如何,所以没关系。
defiant :: (Void -> Int) -> String
defiant f = "Haha"
Int
因为不存在
Void
评估它的值(value)。但这也不是必需的,因为
f
简直是无视!
sleight2 x y = const x y
有点用
y
:
const
的第二个参数只是 rank-0 类型,因此编译器需要在此时解析任何需要的字典。即使
const
最终也抛出
y
离开,它仍然“强制”足够的这个值来表明它不是很好的类型。
关于haskell - 约束消失的情况: Oddities of a higher-rank type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40273246/
我是一名优秀的程序员,十分优秀!