模式匹配,其中模式基于(函数)参数

时间:2011-05-18 02:15:31

标签: generics haskell pattern-matching

我想编写一个兼具

的函数
  • 某个代数数据类型的值构造函数,
  • 同一类型的实际值,

并确定给定值是否来自给定的构造函数。模式匹配似乎很适合这种情况,但匹配的模式必须是函数参数而不是硬编码的构造函数名称。

下面的代码就是我尝试过的,但是GHC在指示的行上报告了一个解析错误。

有没有办法实现这个目标?

data FooBar = Foo Int | Bar String

-- Imagine that these are useful functions.
processInt :: Int -> String
processInt = show
processString :: String -> String
processString = id

-- This should take one of the above functions and adapt it to operate on
-- FooBar values of compatible "type".  Values that match the given FooBar
-- constructor should be "unwrapped" and passed to the given function.
typeCheck :: (a -> FooBar) -> (a -> String) -> (FooBar -> Maybe String)
typeCheck constructor func fooBar = case fooBar of
  (constructor x) -> Just (func x)  -- GHC says "Parse error in pattern: constructor"
  _ -> Nothing

-- Define processing functions that operate on FooBars.
processFoo :: FooBar -> Maybe String
processFoo = typeCheck Foo processInt
processBar :: FooBar -> Maybe String
processBar = typeCheck Bar processString

2 个答案:

答案 0 :(得分:3)

有趣的想法。我想知道你要做什么,因为这是一个非常不寻常的模式匹配问题。

如果可以,你当然可以这样做:

  • 枚举类型
  • 的构造函数
  • 在类型的元素上具有相同性

像这样(我打破了f部分的应用,因为那是正交的):

wasBuilt :: Eq t => (t -> Either t t)   -- ^ the constructor
                 -> Either t t          -- ^ a value
                 -> Maybe t             -- ^ the transformed result

wasBuilt k v = case v of
    Left  x | v == k x    -> Just x
    Right x | v == k x    -> Just x
    _                     -> Nothing

但是有很多样板。这个问题在我身上尖叫着“generics”。尝试不同的方法,并将构造函数反映到数据,然后通常匹配该数据。这将允许您将构造函数视为值,而不是函数。


这大致是我的想法,但请注意,这是一项先进的技术。常规AST上的显式模式匹配更加惯用:

import Generics.SYB

-- only works for unary constructors
sameConstructor :: (Data a, Data b) => (a -> b) -> b -> Bool
sameConstructor k v = toConstr v == toConstr (k undefined)

> sameConstructor (Left :: Char -> Either Char Char) (Right 'x')
False

> sameConstructor (Left :: Char -> Either Char Char) (Left 'x')
True

> sameConstructor (:[]) "haskell"
True

答案 1 :(得分:2)

你可能想看看Type-safe pattern combinators功能性珍珠。虽然它没有与Haskell的模式匹配语法很好地混合,但它确实允许你具有可组合的一流模式的模块性,如果这是你需要的(即如果增加的可组合性超过语法上的不便)。