- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我注意到 GHC 的 ScopedTypeVariables
能够在函数模式中绑定(bind)类型变量,但不能在 let 模式中绑定(bind)类型变量。
作为一个最小的例子,考虑类型
data Foo where Foo :: Typeable a => a -> Foo
如果我想访问 Foo 内部的类型,则以下函数无法编译:
fooType :: Foo -> TypeRep
fooType (Foo x) =
let (_ :: a) = x
in typeRep (Proxy::Proxy a)
但是使用这个技巧将类型变量绑定(bind)移动到函数调用,它可以正常工作:
fooType (Foo x) =
let helper (_ :: a) = typeRep (Proxy::Proxy a)
in helper x
既然 let
绑定(bind)实际上是变相的函数绑定(bind),为什么上面的两个代码片段不等价呢?
(在此示例中,其他解决方案是使用 typeOf x
创建 TypeRep
,或者直接将变量绑定(bind)为 x::a
在顶级函数中。这些选项在我的真实代码中都不可用,并且使用它们并不能回答问题。)
最佳答案
重要的是,函数是伪装的 case
表达式,而不是 let
表达式。 case
匹配和 let
匹配具有不同的语义。这也是您无法匹配在 let
表达式中执行类型细化的 GADT 构造函数的原因。
区别在于,case
匹配在继续之前评估审查者,而 let
匹配在堆上抛出一个 thunk,表示“在需要结果时执行此评估” 。 GHC 不知道如何在惰性可能与它们交互的所有潜在方式中保留本地范围的类型(例如示例中的 a
),因此它不会尝试。如果涉及局部范围的类型,请使用 case
表达式,这样惰性就不会成为问题。
对于您的代码,ScopedTypeVariables
实际上为您提供了一个更简洁的选项:
{-# Language ScopedTypeVariables, GADTs #-}
import Data.Typeable
import Data.Proxy
data Foo where
Foo :: Typeable a => a -> Foo
fooType :: Foo -> TypeRep
fooType (Foo (x :: a)) = typeRep (Proxy :: Proxy a)
关于haskell - 为什么 Haskell 的作用域类型变量不允许在模式绑定(bind)中绑定(bind)类型变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46077442/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!