我有多个数据定义,作为一个简单的例子:
data Fruit = Apple String Bool
| Cherry String String
| Grape String
data Vegetable = Carrot String
| Onion Bool String
| Tomato String String
现在我想要一个应该继续这两种类型的函数,我尝试过这样的事情:
f :: a -> String
f (Carrot s) = s
f (Apple s b) = s
f (Onion b s) = s
...
但这不起作用,因为预期的类型a
无法匹配,例如类型Carrot
。我想知道如何定义一个函数,它可以借助模式匹配或其他技术处理多个现有的独立数据定义。
答案 0 :(得分:6)
一种做你想要做的事情的方法是使用涉及两种食物的新数据类型,所以,我们称之为食物,它将是:
{{1}}
答案 1 :(得分:5)
有两种选择。一个是Damian Lattenero所说的,另一方面,另一个选择是使用类型类。
class Food a where
f :: a -> String
instance Food Fruit where
f (Apple ...) = ...
f (Cherry ...) = ...
f ...
instance Food Vegetable where
f (Carrot ...) = ...
f (Onion ...) = ...
f (Tomato ...) = ...
问题在于你不能拥有食物清单,因为水果和蔬菜是不同类型的。但你可以毫无问题地使用f作为两种类型。
编辑:
另一种选择,即存在量化,将两种类型都放在一个列表中,但只对数据应用f(也使用上面的代码):
{-# LANGUAGE ExistentialQuantification #-}
data F = forall a. (Food a) => F a
instance Food F where
f (F x) = f x
xs :: [F]
xs = [F (Apple ...), F (Carrot ..), F (Tomato ...)]
使用f:
的函数示例mapF :: [F] -> [String]
mapF xs = map f xs