模式匹配与构造函数

dmw*_*w64 4 haskell

对于不同的数据构造函数,我有两个几乎相同的函数,并想知道是否有可能统一两者.一个简约的例子如下

f_maybe :: Maybe a -> a -> a
f_maybe (Just x) _ = x
f_maybe _        x = x
Run Code Online (Sandbox Code Playgroud)

data T a = T1 a | T2 Int | T3

f_t :: T a -> a -> a
f_t  (T1 x) _ = x
f_t  _      x = x
Run Code Online (Sandbox Code Playgroud)

是一种只定义一个由类型构造函数(Maybe或T)和数据构造函数(Just或T1)执行参数化的函数的方法吗?

zak*_*aps 6

一旦Foldable为数据类型实现了实例,这个想法就可以表示为foldr const.

data T a = T1 a | T2 Int | T3

instance Foldable T where
    -- if it's T1, it has a value
    foldMap f (T1 a) = f a
    -- if it's T2 or T3, it's considered "empty"
    foldMap f (T2 _) = mempty
    foldMap f T3     = mempty
Run Code Online (Sandbox Code Playgroud)

您甚至可以让generic-derivingFoldable为您派生上述实例:

{-# LANGUAGE DeriveGeneric #-}

import           Generics.Deriving.Foldable
import           GHC.Generics

data T a = T1 a | T2 Int | T3
    deriving (Generic1)

instance Foldable T where
    foldMap = gfoldMapdefault
Run Code Online (Sandbox Code Playgroud)

(在您的情况下,实例不是模糊的,因为只有一个构造函数可能只包含一个类型的值a.如果数据类型过多复杂,多个构造函数包含一个或多个a,您最好手动执行或仔细检查该包衍生)

ghci的一些结果:

-- `Maybe` already has the instance defined by the standard library
> foldr const 2 (Just 3)
< 3
> foldr const 2 Nothing
< 2

> foldr const 2 (T1 3)
< 3
> foldr const 2 (T2 10)
< 2
> foldr const 2 T3
< 2
Run Code Online (Sandbox Code Playgroud)

  • 通常,我们的想法是定义两种类型实现的类型类; `Foldable`恰好是适用于示例函数的类型类. (3认同)