一次匹配多个数据类型构造函数

Dan*_*kov 9 haskell

让我们说我们有这种类型的声明:

data D a = A a | B a | C a | D a | E a | F a
Run Code Online (Sandbox Code Playgroud)

并希望在其上定义一个函数,该函数将数据构造函数分为两组.写这样的东西会很好:

g x | x `is` [A,B,C] = 1
    | x `is` [D,E,F] = 2
Run Code Online (Sandbox Code Playgroud)

而不是分别在每个构造函数上匹配.

有没有办法实现这个目标?我看着uniplate,却找不到办法.

sth*_*sth 5

如果您经常需要匹配同一组构造函数,则辅助函数可能是最简单的解决方案.例如:

getAbc :: D a -> Maybe a
getAbc (A v) = Just v
getAbc (B v) = Just v
getAbc (C v) = Just v
getAbc _     = Nothing
Run Code Online (Sandbox Code Playgroud)

有了这样的辅助函数,g可以简化定义,如下所示:

g x = g_ (getAbc x)
  where
    g_ (Just v) = 1
    g_ Nothing  = 2
Run Code Online (Sandbox Code Playgroud)

或者,使用maybe功能:

g = maybe 2 (\v -> 1) . getAbc
Run Code Online (Sandbox Code Playgroud)


ken*_*ytm 4

编辑:如果所有构造函数都具有相同类型的字段,您可能会滥用 Functor:

{-# LANGUAGE DeriveFunctor #-}

data D a = A a | B a | C a | D a | E a | F a
    deriving (Eq, Functor)

isCons :: (Eq (f Int), Functor f) => f a -> (Int -> f Int) -> Bool
isCons k s = fmap (const 42) k == s 42

is :: (Eq (f Int), Functor f) => f a -> [Int -> f Int] -> Bool
is k l = any (isCons k) l

g :: D a -> Int
g x | x `is` [A,B,C] = 1
    | x `is` [D,E,F] = 2
Run Code Online (Sandbox Code Playgroud)

你可以尝试

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data

data D a = A a | B a | C a | D a | E a | F a
        deriving (Typeable, Data)

g :: Data a => D a -> Int
g x | y `elem` ["A","B","C"] = 1
    | y `elem` ["D","E","F"] = 2
    where y = showConstr (toConstr x)
Run Code Online (Sandbox Code Playgroud)