Haskell - Using a constant in pattern matching

删除回忆录丶 提交于 2019-12-19 09:38:41

问题


Let's say I have the following code (text in <> is a shorthand, not actually part of the code):

data A = <something>
defaultA :: A
defaultA = <Really complicated expression of type A>

Now I want to have a function pattern match on defaultA, like this:

f defaultA = <case 1>
f _ = <case 2>

However, defaultA in the first line becomes a new variable, not a condition that means the parameter will equal defaultA. The best way I know to achieve something like what I want is:

f x | x == defaultA = <case 1>
f _ = <case 2>

Does anyone know a better way?


回答1:


If the definiton of defaultA consists only of constructor calls, you could use a pattern synonym.

{-# LANGUAGE PatternSynonyms #-}

data A = A Int

pattern DefaultA = A 3

isDefaultA DefaultA = putStrLn "it was a default"
isDefaultA _ = putStrLn "it was not a default"

This isn't a particularly idiomatic deployment of PatternSynonyms though. I'd probably stick with Haskell 98, using a very-slightly-more-verbose guard clause with an equality test.

data A = A Int deriving Eq

defaultA = A 3

isDefaultA a
    | a == defaultA = putStrLn "it was a default"
    | otherwise = putStrLn "it was not a default"

Where pattern synonyms do come in useful is for wrapping up noisy library constructor calls imposed on you when you're doing datatype-generic programming with a pattern like free monads or Data Types a la Carte.

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeOperators #-}

-- fixed point of functor
newtype Expr f = In (f (Expr f))

-- functor coproduct
data (f :+: g) a = Inl (f a) | Inr (g a)


-- now plug in custom code
data Add r = Add_ r r
data Val r = Val_ Int
type HuttonsRazor = Expr (Add :+: Val)

pattern Add x y = In (Inl (Add_ x y))
pattern Val x = In (Inr (Val_ x))

eval :: HuttonsRazor -> Int
eval (Add x y) = eval x + eval y
eval (Val x) = x



回答2:


You can use ViewPattern extension

{-# LANGUAGE ViewPatterns #-}
data A = A Int | B Char deriving (Eq, Show)

complexA = A 34
complexB = B 'z'

isComplexA = (complexA ==)
isComplexB = (complexB ==)

complexF (isComplexA -> True) = print "complexA"
complexF (isComplexB -> True) = print "complexB"
complexF _                    = print "too complex"

main = do
    complexF complexA
    complexF complexB
    complexF $ A 55


来源:https://stackoverflow.com/questions/35429144/haskell-using-a-constant-in-pattern-matching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!