我正在尝试通过查看2006年link上有关comonad应用程序的精彩短篇教育文章来学习一些Haskell,它包含一个像rule (U (a:_) b (c:_)) = not (a && b && not c || (a==b))
这样的表达式U
是一个拉链comonad 。这在data U x = [x] x [x]
和伴随的comonad操作实现中都有说明。
尝试了解更多信息,我试图手动注释表达式的类型。明智的选择似乎是rule :: U Bool -> Bool
,但这似乎有点......限制性。我可以想象其他类型能够具有真实性值,例如Ints(0对应于false,所有其他值可以是True)和其他。
如果有一个名为truthy
的真实类型,我想我可以写rule :: (Truthy t) => U t -> Bool
。由于我想迭代rule
,第一种类型的注释(rule :: U Bool -> Bool
)已经足够好了,但问题仍然困扰着我的大脑。
是否有这样的类型类?如果有,它叫什么?如果没有,为什么没有必要呢?
答案 0 :(得分:6)
离题:一般情况下,我们不会使用类型类来执行您可能称之为仅仅重载的内容,而是在动态语言中找到的类型(例如,使+
意味着&# 34;连接列表"或"添加整数",或重载布尔运算以处理问题中的" truthy"值。不同之处在于我猜我们说好的抽象是使用类型类进行的,这些类具有一组将它们组合在一起的定律,因此您可以编写有用的多态代码。可能是因为我们可以制造一个" truthy"按照这个标准,这个课程很好,但我不确定。
但是为了得到你的问题,肯定有一些类在某种程度上抽象布尔逻辑(这里的研究领域可能是Boolean algebra),这里最相关的可能是Bits
类。 Data.Bits
。
所以你得到:
-- note, the polymorphic `t` has cooties, and we'd need to be able to
-- make the caller polymorphic in a sensible way too for this to make sense
rule :: (Bits t) => U t -> t
rule (U (a:_) b (c:_)) = complement (a .&. b .&. complement c .|. complement (a `xor` b))
上面唯一棘手的问题是a == b
成为罗嗦的更通用的形式complement (a ``xor`` b)
。实际上,如果我们将自己局限于基本操作(AND / OR / NOT),那么==
的更一般形式就非常复杂了:
a .==. b = complement ((a .|. b) .&. complement (a .&. b))
看看这种操作是否或以何种方式使用这种更通用的类型(我不知道它的意图是什么)会很有意思,例如:它是否对Int
做了明智的事情。然后将其与Int
进行比较,如果我们使用了您的" truthy"类。比另一个更有用吗? Bits
版本是否为您提供了对算法的任何新见解,还是只是一个任意的重载?
编辑:这里有一些关于在这个更抽象的领域工作的有趣内容:我们可以使用布尔代数定律来更好地减少和理解我们的表达式。例如,通过handing it off to Wolfram Alpha,我们可以观察到我们的表达式的标准化形式根本不包含c
(你应该仔细检查我的天堂&#t; t在某个地方犯了一个错误),所以我们不妨写一下:
rule (U (a:_) b _) = (a && not b) || (not a && b)
这可能是有趣的见解(在我们的数据结构中是c
甚至是必要的吗?)或者可能表明我们的逻辑中存在错误。