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

Wyz*_*a-- 5 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
Run Code Online (Sandbox Code Playgroud)

Don*_*art 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
Run Code Online (Sandbox Code Playgroud)

但有很多样板。这个问题对我来说是“泛型”。尝试不同的方法,并将构造函数反映到数据,然后在该数据上进行一般匹配,也许。这将允许您将构造函数视为值,而不是函数。


这大概是我的想法,但请注意,这是一项先进的技术。常规 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
Run Code Online (Sandbox Code Playgroud)

  • 不,编写 RPN 计算器很容易。通过尝试对功能进行模式匹配,您刚刚走进了一个有趣的设计角落。在运行时使用简单类型作为类型标记。如果它[对西蒙·佩顿·琼斯来说足够好](http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/PAGES/189.HTM),它会可能也适合你:-) *Peyton Jones [1987,第 10 章]* (2认同)