J'ai écrit quelques fonctions utiles pour effectuer une opération logique. Cela ressemble à (a and b or c) `belongs` x
. Grâce à Num
, IsList
et OverloadedLists
, je peux l'avoir pour les entiers et les listes.Type de conversion automatique en haskell
λ> (1 && 2 || 3) `belongs` [2]
False
λ> (1 && 2 || 3) `belongs` [1, 2]
True
λ> (1 && 2 || 3) `belongs` [3]
True
λ> :set -XOverloadedLists
λ> ([1, 2] && [2, 3] || [3, 4]) `contains` 1
False
λ> ([1, 2] && [2, 3] || [3, 4]) `contains` 2
True
je le fais de cette façon:
newtype BoolLike a = BoolLike ((a -> Bool) -> Bool)
(&&) :: BoolLike a -> BoolLike a -> BoolLike a
BoolLike f && BoolLike g = BoolLike $ \k -> f k P.&& g k
infixr 3 &&
toBoolLike :: a -> BoolLike a
toBoolLike x = BoolLike $ \k -> k x
belongs :: Eq a => BoolLike a -> [a] -> Bool
belongs (BoolLike f) xs = f (\x -> x `elem` xs)
contains :: Eq a => BoolLike [a] -> a -> Bool
contains (BoolLike f) x = f (\xs -> x `elem` xs)
instance Num a => Num (BoolLike a) where
fromInteger = toBoolLike . fromInteger
Ce que je vais faire est de costume pour tous les types, sans convertir manuellement a
à BoolLike a
.
Comment puis-je l'atteindre?
Premier essai:
class IsBool a where
type BoolItem a
toBool :: a -> BoolItem a
instance IsBool (BoolLike a) where
type BoolItem (BoolLike a) = BoolLike a
toBool = id
instance IsBool a where
type BoolItem a = BoolLike a
toBool = toBoolLike
a échoué:
Conflicting family instance declarations:
BoolItem (BoolLike a) -- Defined at BoolLike.hs:54:8
BoolItem a -- Defined at BoolLike.hs:58:8
Il existe le package [Boolean] (https://hackage.haskell.org/package/Boolean). –