- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
为什么 GHC 从关联数据的强制性推断统一,为什么它与自己的检查类型签名相矛盾?
问题
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
module Lib
(
) where
import Data.Coerce
class Foo a where
data Bar a
data Baz a = Baz
{ foo :: a
, bar :: Bar a
}
type BarSame a b = (Coercible (Bar a) (Bar b), Coercible (Bar b) (Bar a))
withBaz :: forall a b. BarSame a b => (a -> b) -> Baz a -> Baz b
withBaz f Baz{..} = Baz
{ foo = f foo
, bar = coerce bar
}
这一切都很好——GHC 会很高兴地编译这段代码,并且相信
withBaz
具有声明的签名。
instance (Foo a) => Foo (Maybe a) where
data Bar (Maybe a) = MabyeBar (Bar a)
toMaybeBaz :: Baz a -> Baz (Maybe a)
toMaybeBaz = withBaz Just
这给出了一个错误 - 但一个非常奇怪的错误:
withBaz Just
^^^^^^^^^^^^
cannot construct the infinite type: a ~ Maybe a
确实,如果我进入 GHCi,并要求它给我
withBaz
的类型:
ghc>:t withBaz
withBaz :: (b -> b) -> Baz b -> Baz b
那不是我给它的签名。
withBaz
的类型参数好像他们必须统一,因为它在推断
Coercible a b
来自
Coercible (Bar a) (Bar b)
.但是因为它是一个数据族,它们甚至不需要是
Coercible
- 当然不能统一。
instance (Foo a) => Foo (Maybe a) where
newtype Bar (Maybe a) = MabyeBar (Bar a)
即 - 将数据系列声明为
newtype
, 而不是
data
.这似乎与 GHC 对
Coercible
的处理一致。在一般的语言中,在那个
data Id a = Id a
不会导致
Coercible
要生成的实例 - 即使它绝对应该强制为
a
.使用上述声明,这将出错:
wrapId :: a -> Id a
wrapId = coerce
但是使用
newtype
宣言:
newtype Id a = Id a
然后
Coercible
实例存在,并且
wrapId
编译。
最佳答案
我相信@dfeuer 关于缺乏对类型/数据系列的“角色”支持的评论提供了答案。
对于顶级,data
-定义的参数化类型:
data Foo a = ...
类型的强制力
Foo a
和
Foo b
取决于参数
a
的作用.特别是,如果
a
s 角色是名义上的,那么
Foo a
和
Foo b
是可强制的当且仅当
a
和
b
是完全相同的类型。
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RoleAnnotations #-}
import Data.Coerce
type role Foo nominal
data Foo a = Foo
foo :: (Coercible (Foo a) (Foo b)) => a -> b
foo = undefined
因为
nominal
参数的作用
a
在
Foo a
,
foo
的类型实际上简化为
b -> b
:
λ> :t foo
foo :: b -> b
如果角色注释从
nominal
更改至
representational
, 类型简化为
Coercible a b => a -> b
, 如果角色更改为
phantom
(
Foo
这个特定声明的默认值,因为
a
没有出现在右侧),类型被简化为
a -> b
.这一切都符合预期,并且对应于每个角色的定义。
Foo
的声明和:
data Foo a = Foo a
然后
phantom
角色将不再被允许,但
foo
的推断类型在其他两个角色下将与以前完全相同。
data
切换,则有一个重要的区别。到
newtype
.和:
newtype Foo a = Foo a
你会发现即使使用
type role Foo nominal
,
foo
的推断类型将是
Coercible b a => a -> b
而不是
b -> b
.这是因为类型安全强制的算法处理
newtype
s 不同于“等效”
data
类型,正如您在问题中所指出的那样——无论类型参数的作用如何,只要构造函数在范围内,它们总是可以通过展开立即强制执行。
nominal
的角色是一致的。 .虽然我在 GHC 手册中找不到它,但这似乎是设计的行为,并且有
an open ticket确认所有数据/类型系列都分配了所有参数
nominal
角色并提议放宽此限制,而@dfeuer 实际上有一个
detailed proposal从去年十月开始。
关于haskell - 为什么 GHC 在使用 Coercible 约束时会自相矛盾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65438431/
runghc 和 ghc 有什么区别? 我运行了一个简短的程序,似乎可以用两者编译,除了我用 runghc 得到了以下内容,但不是普通的 ghc: error: Variable not in sco
如果 friend 想要运行我的 Haskell 二进制文件,他是否必须先安装 Haskell,还是可以立即自行运行二进制文件? Mac、Windows 和 Linux 上的答案相同吗? 最佳答案 G
ffunction glMultiDrawElements 需要一个指向指针的指针作为其参数之一。如何从 StorableArray Int a 获取 Ptr(Ptr a) ? 最佳答案 您需要先将索
module Has (r,p,s) where import Prelude ((==),Bool(..),otherwise,(||),Eq) import qualified Data.List
我已经构建了 ghc-HEAD,我想尝试构建所有的 stackage lts 或 nightly 看看它能做多少。 无论我说什么都无法说服 stack 使用我的新 ghc 构建任何东西。我尝试设置如下
我正在使用 Emacs (24.3.1) 在 haskell-mode 中与 ghc-mod 一起使用 Haskell。 现在除了一件烦人的事情外,一切都很好: GHC 信息缓冲区中的每个输出仅包含第
为什么升级到 OSX Mavericks 后我的 GHC 7.6.3 不能工作? 最佳答案 花了很长时间才弄清楚如何同时使用 OSX 10.9 和 GHC 7.6.3,这里有一些技巧可以帮助您重新构建
我有一个带有 cabal 文件的主要 Haskell 可执行程序。在那里,我指定 ghc-options . 这个可执行文件链接到野外的其他库。请问ghc-options忽略这些库的 cabal 文件
我有一个使用 -Wall 编译的库,并且我有一个使用 -Wall -Wno-incomplete-patterns 的测试套件 当我使用 stack ghci --test 启动 ghci 时,ghc
我正在尝试使用以下脚本在 Windows 上安装 GHC(并将 ghc 放在路径中),但是当我尝试运行 ghci --version 时它失败了。我认为脚本有问题。 install: - ps:
我在 $HOME 中安装了 ghc-7.2.2 unknown linux tar.bz2在archlinux上。 在使用 cabal-dev 成功安装多个软件包后,尝试安装例如。我得到的解析数字、文
想法 我正在写 DSL ,编译为 Haskell。 该语言的用户可以定义自己的不可变数据结构和相关函数。关联函数是指属于数据结构的函数。 例如,用户可以编写(在“pythonic”伪代码中): dat
(我的问题是在没有 haskell-platform、ghc、cabal 等的情况下分发二进制文件) 我需要部署一个结构良好的 haskell 应用程序(Yesod 脚手架),但我有磁盘空间限制。 G
我试图将 Cygwin 安装程序指向 http://haskell.org/ghc/cygwin ,但安装程序无法找到 setup.ini.sig。如果可能的话,我该如何编辑我的 .bashrc 以引
我有一个现有的 Haskell 函数,它使用 GHC API 从模块中动态加载已编译的代码。它基于博客文章中的代码 Dynamic Compilation and Loading of Modules
我使用:Ubuntu 上的 GHC 7.6.3(通过 apt-get install haskell-platform) 从当前存储库安装它。 正在尝试安装ghc-mod ,因为我的 ide 插件需要
AFAIK,有两种方法可以在 Haskell 中获取用于调试的调用堆栈: 添加 HasCallStack代码中的约束 使用 ghc -prof -fprof-auto-top 编译代码 我的测试代码:
我想用 64 位 GHC 构建 32 位 DLL。这是最小的例子。 测试.hs {-# LANGUAGE ForeignFunctionInterface #-} module Test where
ghc-gc-tune 0.2.1 可以与 ghc 7.4.1 一起使用吗?看来 ghc-gc-tune 已经有一段时间没有更新了,可能只适用于 ghc 6.x?我找不到任何可靠的信息。 我收到以下错
语言扩展 ExplicitForall 使得使用 forall 绑定(bind)类型变量成为可能但不是必需的。 例如,下面的程序可以编译 {-# LANGUAGE ExplicitForAll #-}
我是一名优秀的程序员,十分优秀!