I’d like to write a function that takes both
- a value constructor for a certain algebraic data type, and
- an actual value of that same type,
and determines whether the given value is “made from” the given constructor. Pattern matching seems like a natural fit for this, but the pattern to match against would have to be a function parameter instead of a hard-coded constructor name.
The code below is what I’ve tried, but GHC reports a parse error on the line indicated.
Is there a way to accomplish this?
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
Interesting idea. I wonder what you’re trying to do, since this is quite an unusual pattern matching problem.
You can certainly do it if you can:
Like so (I break out the application of
fpart, since that is orthogonal):But there’s a lot of boilerplate. This problem screams “generics” at me. Try a different approach, and reflect the constructor to data, then match generically on that data, perhaps. This will allow you to treat the constructors as values, instead of functions.
Here’s roughly what I was thinking, but note, this is an advanced technique. Explicit pattern matching on a regular AST is much, much more idiomatic: