Haskell - 调用类型类中定义的函数
给定一个类型类:
class AnimalTrainer animal food where
getFood :: animal -> (food, Int) -- Returns the food and the quantity
feed :: animal -> (food, Int) -- Returns the leftovers
feed a = feed' (getFood a) -- Provide a default implementation
where feed' (f, n) = (f, n - 1)
和一个实例:
data Animal = Dog | Cat
data Food = Meat | Milk
instance AnimalTrainer Animal Food where
getFood Dog = (Meat, 2)
getFood Cat = (Milk, 3)
如何编写另一个函数(在其他地方)来调用类型类中定义的 feed 函数?示例:
feedEverything :: Bool
feedEverything = snd (feed Dog) == 0
谢谢
Given a typeclass:
class AnimalTrainer animal food where
getFood :: animal -> (food, Int) -- Returns the food and the quantity
feed :: animal -> (food, Int) -- Returns the leftovers
feed a = feed' (getFood a) -- Provide a default implementation
where feed' (f, n) = (f, n - 1)
And an instance:
data Animal = Dog | Cat
data Food = Meat | Milk
instance AnimalTrainer Animal Food where
getFood Dog = (Meat, 2)
getFood Cat = (Milk, 3)
How can I write another function (somewhere else) that calls the feed function defined in the typeclass? Example:
feedEverything :: Bool
feedEverything = snd (feed Dog) == 0
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是 Haskell 无法弄清楚你想要使用什么类型的食物。它看到一个实例:
但也许在某个地方还有第二个实例......
所以你需要告诉 Haskell 动物只获取食物,而不是其他东西,例如毒药。
解决方案 1:您可以使用函数依赖:
这告诉 Haskell 对于每种动物类型,它只会吃一种食物类型。
解决方案 2:您还可以使用类型系列。
我个人认为这个解决方案有点深奥,而且语法有点不太自然。但这个例子是人为的,所以为了完整性我将其包括在内。
解决方案 3:您可以在每次调用 feed 时添加显式类型注释。
The problem is that Haskell can't figure out what type you want to use for food. It sees one instance:
But maybe there is a second instance somewhere...
So you need to tell Haskell that animals get food only, and not something else like poison.
Solution 1: You can use functional dependencies:
This tells Haskell that for each animal type, there is only one food type that it will eat.
Solution 2: You can also use type families.
I personally consider this solution a little more esoteric, and the syntax a little less natural. But the example is contrived, so I include this for completeness.
Solution 3: You could add explicit type annotations whenever you call feed.