{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -- | Another way to desugar list literals. -- -- An explicit list expression, e.g. @[1, True]@ is desugared to -- -- @ -- cons 1 (cons True nil) -- @ -- -- This desugaring uses bidirectional functional dependencies to -- make `cons` infer more. The trade-off is that we can have strictly -- less instances. -- -- Enabled with: -- -- @ -- {-\# OPTIONS_GHC -fplugin=Overloaded -- -fplugin-opt=Overloaded:Lists=Overloaded.Lists.Bidi.nil=Overloaded.Lists.Bidi.cons -- @ -- module Overloaded.Lists.Bidi ( nil, Cons (..), Uni.fromList, ) where import Data.SOP.NP (NP (..), POP (..)) import qualified Data.IntMap as IM import qualified Data.IntSet as IS import qualified Data.Sequence as Seq import qualified Data.Map as M import qualified Data.Set as S import qualified Data.Type.Nat as N import qualified Data.Vec.Lazy as Vec import qualified Overloaded.Lists as Uni ------------------------------------------------------------------------------- -- Classes ------------------------------------------------------------------------------- nil :: Uni.Nil a => a nil = Uni.nil {-# INLINE nil #-} -- | Bidirectional class for Cons ':'. -- -- @since 0.2 class Uni.Cons x ys zs => Cons x ys zs | zs -> x ys, x ys -> zs where cons :: x -> ys -> zs cons = Uni.cons infixr 5 `cons` ------------------------------------------------------------------------------- -- base ------------------------------------------------------------------------------- instance (a ~ b, b ~ c) => Cons a [b] [c] ------------------------------------------------------------------------------- -- containers ------------------------------------------------------------------------------- instance (Ord a, a ~ b, b ~ c) => Cons a (S.Set a) (S.Set a) instance Cons Int IS.IntSet IS.IntSet instance (a ~ b, b ~ c) => Cons a (Seq.Seq b) (Seq.Seq c) instance (Ord k, k ~ k1, k ~ k2, v ~ v1, v ~ v2) => Cons (k, v) (M.Map k1 v1) (M.Map k2 v2) instance (i ~ Int, a ~ b, b ~ c) => Cons (i, a) (IM.IntMap b) (IM.IntMap c) ------------------------------------------------------------------------------- -- vec ------------------------------------------------------------------------------- instance (a ~ b, b ~ c, m ~ 'N.S n) => Cons a (Vec.Vec n b) (Vec.Vec m c) ------------------------------------------------------------------------------- -- sop-core ------------------------------------------------------------------------------- instance (f ~ g, g ~ h, xxs ~ (x ': xs)) => Cons (f x) (NP g xs) (NP h xxs) instance (f ~ g, g ~ h, xsxss ~ (xs ': xss)) => Cons (NP f xs) (POP g xss) (POP h xsxss)