#haskell
#haskell
Вопрос:
data Prop = Const Bool
| Var Char
| Not Prop
| And Prop Prop
| Imply Prop Prop
Я реализую вышеупомянутый конструктор данных с небольшим дополнением,
data Prop = Const Bool
| Var Char
| Not Prop
| Or Prop Prop
| And Prop Prop
| Imply Prop Prop
Когда я пытаюсь создать другой конструктор данных ниже, который использует ранее определенный конструктор,
data Formula = Const Bool
| Var Prop
| Not Formula
| And Formula Formula
| Or Formula Formula
| Imply Formula Formula
Я получаю эту ошибку:
«Множественные объявления «Const»»
Та же ошибка следует с Not
, And
, Imply
, и Or
. Почему Haskell не разрешает это?
Комментарии:
1. Подумайте о том, каким был бы тип
Const
, если бы это было разрешено.
Ответ №1:
Haskell не разрешает этого, потому что это было бы неоднозначно. Конструктор значений Prop
фактически является функцией, что может быть понятнее, если вы спросите GHCi о его типе:
> :t Const
Const :: Bool -> Prop
Если вы попытаетесь добавить еще один Const
конструктор в тот же модуль, у вас будут две «функции», вызываемые Const
в одном модуле. У вас этого не может быть.
Комментарии:
1. Обратите внимание, что это, вероятно, не совсем непреодолимая проблема, поскольку такой перегруженный конструктор имеет много общего с методом класса. Будет ли какая-либо такая реализация стоить проблем — это другой вопрос.
Ответ №2:
Это несколько ужасно, но в основном позволит вам делать то, что вы хотите:
{-# LANGUAGE PatternSynonyms, TypeFamilies, ViewPatterns #-}
data Prop = PropConst Bool
| PropVar Char
| PropNot Prop
| PropOr Prop Prop
| PropAnd Prop Prop
| PropImply Prop Prop
data Formula = FormulaConst Bool
| FormulaVar Prop
| FormulaNot Formula
| FormulaAnd Formula Formula
| FormulaOr Formula Formula
| FormulaImply Formula Formula
class PropOrFormula t where
type Var t
constructConst :: Bool -> t
deconstructConst :: t -> Maybe Bool
constructVar :: Var t -> t
deconstructVar :: t -> Maybe (Var t)
constructNot :: t -> t
deconstructNot :: t -> Maybe t
constructOr :: t -> t -> t
deconstructOr :: t -> Maybe (t, t)
constructAnd :: t -> t -> t
deconstructAnd :: t -> Maybe (t, t)
constructImply :: t -> t -> t
deconstructImply :: t -> Maybe (t, t)
instance PropOrFormula Prop where
type Var Prop = Char
constructConst = PropConst
deconstructConst (PropConst x) = Just x
deconstructConst _ = Nothing
constructVar = PropVar
deconstructVar (PropVar x) = Just x
deconstructVar _ = Nothing
constructNot = PropNot
deconstructNot (PropNot x) = Just x
deconstructNot _ = Nothing
constructOr = PropOr
deconstructOr (PropOr x y) = Just (x, y)
deconstructOr _ = Nothing
constructAnd = PropAnd
deconstructAnd (PropAnd x y) = Just (x, y)
deconstructAnd _ = Nothing
constructImply = PropImply
deconstructImply (PropImply x y) = Just (x, y)
deconstructImply _ = Nothing
instance PropOrFormula Formula where
type Var Formula = Prop
constructConst = FormulaConst
deconstructConst (FormulaConst x) = Just x
deconstructConst _ = Nothing
constructVar = FormulaVar
deconstructVar (FormulaVar x) = Just x
deconstructVar _ = Nothing
constructNot = FormulaNot
deconstructNot (FormulaNot x) = Just x
deconstructNot _ = Nothing
constructOr = FormulaOr
deconstructOr (FormulaOr x y) = Just (x, y)
deconstructOr _ = Nothing
constructAnd = FormulaAnd
deconstructAnd (FormulaAnd x y) = Just (x, y)
deconstructAnd _ = Nothing
constructImply = FormulaImply
deconstructImply (FormulaImply x y) = Just (x, y)
deconstructImply _ = Nothing
pattern Const x <- (deconstructConst -> Just x) where
Const x = constructConst x
pattern Var x <- (deconstructVar -> Just x) where
Var x = constructVar x
pattern Not x <- (deconstructNot -> Just x) where
Not x = constructNot x
pattern Or x y <- (deconstructOr -> Just (x, y)) where
Or x y = constructOr x y
pattern And x y <- (deconstructAnd -> Just (x, y)) where
And x y = constructAnd x y
pattern Imply x y <- (deconstructImply -> Just (x, y)) where
Imply x y = constructImply x y
{-# COMPLETE Const, Var, Not, Or, And, Imply :: Prop #-}
{-# COMPLETE Const, Var, Not, Or, And, Imply :: Formula #-}
Если https://gitlab.haskell.org/ghc/ghc/-/issues/8583 были когда-либо сделаны, то это можно было бы существенно очистить.