在Haskell中,强制和受限身份验证

3

为什么coerce没有默认的身份(identity)限制呢?


import Data.Coerce
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

newtype Id a = Id a

a :: Id Int
a = coerce 3 -- bad

-- • Couldn't match representation of type ‘a0’ with that of ‘Int’ arising from a use of ‘coerce’
-- • Ambiguous type variable ‘a0’ arising from the literal ‘3’
--   prevents the constraint ‘(Num a0)’ from being solved.
--   Probable fix: use a type annotation to specify what ‘a0’ should be.
--   These potential instances exist:
--     instance Num Integer -- Defined in ‘GHC.Num’
--     instance Num Double -- Defined in ‘GHC.Float’
--     instance Num Float -- Defined in ‘GHC.Float’

b :: Id Int
b = coerce (3 :: Int)

我想到可以尝试使用a0 ~ Int(或其他一般的约束条件)来解决这个问题,因为身份(和合并约束条件)似乎始终是一个选项。
2个回答

2
下面的代码本质上是不明确的。
a :: Id Int
a = coerce 3

因为它实际上意味着

a :: Id Int
a = coerce (fromInteger (3 :: Integer))

在这里,fromInteger 可以返回 任何 实现了 Num 类型类的类型 T,只要该类型可以通过 coerce 转换为 Id Int

当然,一种可能的解决方案是 T ~ Int,但这不是唯一的解决方案。考虑下面这个人为构造的例子:

newtype T = T Int

instance Num T where
   fromInteger n = T (fromInteger n + 1)

a :: Id Int
a = coerce (3 :: T)
-- which means  a = coerce (fromInteger (3 :: Integer) :: T)

在这里,我们有a = Id 4,因为fromInteger增加了Int,这与a = coerce (3 :: Int)得到的Id 3不同。
在对coerce 3进行类型推断时,Haskell无法知道我们是指coerce (3 :: Int)还是coerce (3 :: T),所以代码本质上是不明确的,并被拒绝。

1
@DanielWagner 这将是一个特殊情况:我们将解决Coercible约束,不像其他约束。我们已经有了“特殊”的类(数字默认值),我们还需要更多吗?如果程序员打算使用coerce(3 :: T)但忘记了::T怎么办?如果我们有Coercible a X,Coercible b Y,Coercible a b,其中X可强制转换为Y;我们得到a~b~X还是a~b~Y?也许在这种情况下,魔法不应该触发,并且仍应生成模糊错误。我并不强烈反对魔法,但我确实害怕不可预测的魔法。 - chi
1
“不可预测的”魔法肯定是最糟糕的,而默认值则很危险。(例如,我没有考虑到IntInteger之间的区别)。我可以想象,“失败重试”解决方案可能会触发一些意想不到的循环(?)。话虽如此,可强制转换在受信任的代码库中。问题可以被框架化(我认为)超越了Coercible:如果我们将这些类型类(和类型..)视为一个逻辑系统,那么实际上是通过某些其他关系对某些关系进行商集。 - nicolas
我想我们将获得所有这些关系的自反传递闭包。也就是说,我认为这是一种通过饱和同一类别中各个元素上的关系而不实际使用商类别来进行商的方法。这可能是它的实现方式。我认为Typeable会生成很多这样的约束条件。 - nicolas

2

如果我正确理解了这个问题,那么答案可能是很无聊的:没有人既有想法又有时间去完成添加特殊情况到类型检查器所需的工程工作。我没有看到任何技术上不做这件事的理由,如果每次进行默认操作时发出警告(或将其隐藏在语言扩展后面,或两者兼备),我认为 GHC HQ 很可能会接受这样的补丁。


谢谢。我在想我是否对情况有了错误的认识。这似乎是一个很好的项目。不确定我能否完成它,我应该将其发布到 GHC 的 GitLab 上,以便有人可以接手它。 - nicolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接