用于处理多个现有独立数据定义的函数

时间:2017-12-27 14:33:19

标签: haskell pattern-matching

我有多个数据定义,作为一个简单的例子:

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。我想知道如何定义一个函数,它可以借助模式匹配或其他技术处理多个现有的独立数据定义。

2 个答案:

答案 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