haskell - 如何在 Haskell 中为存在类型编写 getter

标签 haskell

感谢this question的答复我定义了一个这样的类型:

data Chain = forall a. Integral a => Chain [[a]] [a] a a

我需要为每个字段或参数编写一个 getter 函数(如果您愿意的话)。这是我的第一次尝试:

getSimplices (Chain simplices _ _ _) = simplices

但是当我尝试编译 ghc 时出现以下错误:

Chain.hs:10:40: error:
• Couldn't match expected type ‘t’ with actual type ‘[[a]]’
    because type variable ‘a’ would escape its scope
  This (rigid, skolem) type variable is bound by
    a pattern with constructor:
      Chain :: forall a. Integral a => [[a]] -> [a] -> a -> a -> Chain,
    in an equation for ‘getSimplices’
    at Chain.hs:10:15-35
• In the expression: simplices
  In an equation for ‘getSimplices’:
      getSimplices (Chain simplices _ _ _) = simplices
• Relevant bindings include
    simplices :: [[a]] (bound at Chain.hs:10:21)
    getSimplices :: Chain -> t (bound at Chain.hs:10:1)

我是这样修复的:

getSimplices (Chain simplices _ _ _) = map (map fromIntegral) simplices

即使某种 ghc 魔法可以防止 setter/getter 变得异常缓慢,我认为以这种方式修复某些东西是非常残暴的。有没有更好的方法来为这样的类型定义 getter?

最佳答案

存在类型的构造函数必然“忘记”a:

Chain :: Integral a => [[a]] -> [[a]] -> a -> a -> Chain

请注意结果类型如何不再依赖于 a

这样做的结果是,当我们在Chain上进行模式匹配时,我们无法对a是什么做出任何假设。毕竟我们在构建时可以选择任何东西。我们对 a 唯一的了解是它必须是整型。因此,我们只能使用Integral类型类的方法进行访问。

一般规则是,当我们在Chain上进行模式匹配时,我们必须返回一个不依赖于a的类型值>。像这样的 setter/getter

getter (Chain _ _ x _) = x

违反了该规则。毕竟,它会是什么类型?

getter :: Chain -> ???

当然不是

getter :: Chain -> a

这意味着我们可以从Chain中提取我们想要的任何类型。这实际上是行不通的:我们不能自由选择放入什么类型,然后也可以自由选择取出什么类型。

但是,我们可以做的是利用Integral:

getter :: Chain -> Integer
getter (Chain _ _ x _) = fromIntegral x

Integer 不依赖于 a,所以没问题。

关于haskell - 如何在 Haskell 中为存在类型编写 getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47024544/

相关文章:

haskell - 如何有条件地绑定(bind)在 do block 中?

haskell - 创建新处理程序后清空 do block yesod

haskell - haskell 的树

haskell - 通过 IO 了解 Haskell 中的纯函数

haskell - 如何比较字符与 Haskell 中的数字?

haskell - 正确导入模块,其中某些定义仅对限定名称可见

haskell - 制作在自身上运行其输入的函数时出现无限类型错误

haskell - 如何在 Rust 中复制 Haskell 的 `scanl (+) 0 xs`?

haskell - 值得阅读和学习的好 Haskell 资源

haskell - 这个haskell函数中的这些值来自哪里?