感谢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/