gpt4 book ai didi

haskell - 我可以静态拒绝存在类型的不同实例吗?

转载 作者:行者123 更新时间:2023-12-02 02:50:17 27 4
gpt4 key购买 nike

第一次尝试

很难使这个问题简洁,但提供一个最小的例子,假设我有这种类型:

{-# LANGUAGE GADTs #-}
data Val where
Val :: Eq a => a -> Val

这种类型让我愉快地构建了以下异构列表:
l = [Val 5, Val True, Val "Hello!"]

但是,唉,当我写下 Eq例如,事情出错了:
instance Eq Val where
(Val x) == (Val y) = x == y -- type error

啊,所以我们 Could not deduce (a1 ~ a) .非常正确;定义中没有任何内容说 xy必须是同一类型。事实上,重点是允许它们不同的可能性。

第二次尝试

让我们带 Data.Typeable混合,并且只有在它们碰巧是相同类型时才尝试比较它们:
data Val2 where
Val2 :: (Eq a, Typeable a) => a -> Val2

instance Eq Val2 where
(Val2 x) == (Val2 y) = fromMaybe False $ (==) x <$> cast y

这很不错。如 xy是相同的类型,它使用底层 Eq实例。如果它们不同,它只返回 False .但是,此检查会延迟到运行时,允许 nonsense = Val2 True == Val2 "Hello"打字检查没有投诉。



我意识到我在这里与依赖类型调情,但是 Haskell 类型系统是否有可能静态拒绝类似上面的内容 nonsense ,同时允许类似 sensible = Val2 True == Val2 False交还 False在运行时?

我处理这个问题的次数越多,我似乎就越需要采用 HList 的一些技术。将我需要的操作实现为类型级函数。但是,我对使用existentials 和GADT 比较陌生,我很想知道是否可以找到解决方案。所以,如果答案是否定的,我非常感谢讨论这个问题到底在什么地方达到了这些功能的限制,以及对适当的技术、HList 或其他方面的插入。

最佳答案

为了根据所包含的类型做出类型检查决定,我们需要通过将其作为类型参数公开来“记住”所包含的类型。

data Val a where
Val :: Eq a => a -> Val a

现在 Val IntVal Bool是不同的类型,所以我们可以很容易地强制要求只允许相同类型的比较。
instance Eq (Val a) where
(Val x) == (Val y) = x == y

但是,由于 Val IntVal Bool是不同的类型,我们不能在没有附加层的情况下将它们混合在一个列表中,该层会再次“忘记”所包含的类型。
data AnyVal where
AnyVal :: Val a -> AnyVal

-- For convenience
val :: Eq a => a -> AnyVal
val = AnyVal . Val

现在,我们可以写
[val 5, val True, val "Hello!"] :: [AnyVal]

现在应该很清楚了,您无法使用单一数据类型同时满足这两个要求,因为这样做需要同时“忘记”和“记住”所包含的类型。

关于haskell - 我可以静态拒绝存在类型的不同实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7563459/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com