{-# LANGUAGE GADTs, TypeOperators, FlexibleInstances, TemplateHaskell #-}
{-# LANGUAGE ViewPatterns, QuasiQuotes, DataKinds, PolyKinds #-}
module Data.Binding.Hobbits.Liftable where
import Data.Type.RList
import Data.Binding.Hobbits.Mb
import Data.Binding.Hobbits.Internal.Mb
import Data.Binding.Hobbits.QQ
import Data.Binding.Hobbits.Closed
import Data.Binding.Hobbits.NuMatching
import Data.Binding.Hobbits.NuMatchingInstances
import Data.Ratio
import Data.Proxy
import Numeric.Natural
import Data.Type.Equality
class NuMatching a => Liftable a where
mbLift :: Mb ctx a -> a
instance Liftable Char where
mbLift (ensureFreshPair -> (_, c)) = c
instance Liftable Int where
mbLift (ensureFreshPair -> (_, i)) = i
instance Liftable Integer where
mbLift (ensureFreshPair -> (_, i)) = i
instance Liftable (Closed a) where
mbLift (ensureFreshPair -> (_, c)) = c
instance Liftable Natural where
mbLift (ensureFreshPair -> (_, i)) = i
instance Liftable (Member c a) where
mbLift [nuP| Member_Base |] = Member_Base
mbLift [nuP| Member_Step m |] = Member_Step (mbLift m)
mbList :: NuMatching a => Mb c [a] -> [Mb c a]
mbList [nuP| [] |] = []
mbList [nuP| x : xs |] = x : mbList xs
instance (Integral a, NuMatching a) => NuMatching (Ratio a) where
nuMatchingProof =
isoMbTypeRepr (\r -> (numerator r, denominator r)) (\(n,d) -> n%d)
instance (Integral a, Liftable a) => Liftable (Ratio a) where
mbLift mb_r =
(\(n,d) -> n%d) $ mbLift $ fmap (\r -> (numerator r, denominator r)) mb_r
instance Liftable a => Liftable [a] where
mbLift [nuP| [] |] = []
mbLift [nuP| x : xs |] = (mbLift x) : (mbLift xs)
instance Liftable () where
mbLift [nuP| () |] = ()
instance (Liftable a, Liftable b) => Liftable (a,b) where
mbLift [nuP| (x,y) |] = (mbLift x, mbLift y)
instance Liftable Bool where
mbLift [nuP| True |] = True
mbLift [nuP| False |] = False
instance Liftable a => Liftable (Maybe a) where
mbLift [nuP| Nothing |] = Nothing
mbLift [nuP| Just mb_a |] = Just $ mbLift mb_a
instance (Liftable a, Liftable b) => Liftable (Either a b) where
mbLift [nuP| Left mb_a |] = Left $ mbLift mb_a
mbLift [nuP| Right mb_b |] = Right $ mbLift mb_b
instance Liftable (a :~: b) where
mbLift [nuP| Refl |] = Refl
instance Liftable (Proxy (a :: k)) where
mbLift [nuP| Proxy |] = Proxy
instance Eq a => Eq (Mb ctx a) where
mb1 == mb2 =
mbLift $ nuMultiWithElim (\_ (_ :>: a1 :>: a2) ->
a1 == a2) (MNil :>: mb1 :>: mb2)