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)
有趣的想法。我想知道你想做什么,因为这是一个非常不寻常的模式匹配问题。
如果你能做到的话,你当然可以做到:
像这样(我分解了部分的应用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)