Haskell - Использование константы в сопоставлении с образцом
Допустим, у меня есть следующий код (текст в <>
это сокращение, а не часть кода):
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>
Кто-нибудь знает лучший способ?
2 ответа
Если определение defaultA
состоит только из вызовов конструктора, вы можете использовать синоним шаблона.
{-# 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"
Синонимы шаблона полезны только для того, чтобы обернуть зашумленные вызовы конструктора библиотеки, навязываемые вам, когда вы выполняете общее программирование типа данных с шаблоном, таким как бесплатные монады или типы данных по меню.
{-# 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
Вы можете использовать расширение 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