4

假设我有以下代码(文本<>是简写,实际上不是代码的一部分):

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

现在我想在 上进行函数模式匹配defaultA,如下所示:

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

但是,defaultA在第一行中变成了一个新变量,而不是意味着参数将等于的条件defaultA。我知道实现我想要的东西的最好方法是:

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

有谁知道更好的方法?

4

2 回答 2

7

如果 的定义defaultA仅包含构造函数调用,则可以使用模式 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"

不过,这并不是一个特别惯用的部署PatternSynonyms。我可能会坚持使用 Haskell 98,使用带有相等测试的稍微冗长的保护子句。

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"

模式同义词确实有用的地方是,当您使用免费 monadsData 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
于 2016-02-16T11:30:11.927 回答
2

您可以使用ViewPattern扩展

{-# 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
于 2016-02-16T10:22:26.857 回答