给出一个类型类:
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)
Run Code Online (Sandbox Code Playgroud)
一个例子:
data Animal = Dog | Cat
data Food = Meat | Milk
instance AnimalTrainer Animal Food where
getFood Dog = (Meat, 2)
getFood Cat = (Milk, 3)
Run Code Online (Sandbox Code Playgroud)
如何编写调用类型类中定义的feed函数的另一个函数(在其他地方)?例:
feedEverything :: Bool
feedEverything = snd (feed Dog) == 0
Run Code Online (Sandbox Code Playgroud)
谢谢
Die*_*Epp 10
问题是Haskell无法确定您想要用于食物的类型.它看到一个实例:
instance AnimalTrainer Animal Food
Run Code Online (Sandbox Code Playgroud)
但也许在某个地方有第二个实例......
instance AnimalTrainer Animal Poison
Run Code Online (Sandbox Code Playgroud)
所以你需要告诉Haskell,动物只能获得食物,而不是像毒药那样的东西.
解决方案1:您可以使用功能依赖项:
class AnimalTrainer animal food | animal -> food where
...
Run Code Online (Sandbox Code Playgroud)
这告诉Haskell,对于每种动物类型,它只会吃一种食物类型.
解决方案2:您还可以使用类型系列.
class AnimalTrainer animal where
type AnimalFood animal :: *
getFood :: animal -> (AnimalFood animal, Int)
feed :: animal -> (AnimalFood animal, Int)
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 where
type AnimalFood Animal = Food
getFood Dog = (Meat, 2)
getFood Cat = (Milk, 3)
Run Code Online (Sandbox Code Playgroud)
我个人认为这个解决方案更加深奥,语法不那么自然.但这个例子是人为的,所以我把它包括在内是为了完整性.
解决方案3:您可以在调用feed时添加显式类型注释.
feedEverything = snd ((feed :: Animal -> (Food, Int)) Dog) == 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
232 次 |
| 最近记录: |