hkd-0.1: example/NP.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ <800
{-# LANGUAGE UndecidableInstances #-}
#endif
module Main where
#if MIN_VERSION_base(4,9,0)
import Data.Kind (Type)
#else
#define Type *
#endif
import Data.HKD
import Control.Applicative as A (Applicative (pure), liftA2)
import Data.Monoid as Mon (Monoid (..))
-- We can define flipped NP (as in sop-code), which would be instance
-- of classes in Data.HKD
data NP (xs :: [k]) (f :: k -> Type) where
Nil :: NP '[] f
(:*) :: f x -> NP xs f -> NP (x ': xs) f
instance FFunctor (NP xs) where
ffmap _ Nil = Nil
ffmap f (x :* xs) = f x :* ffmap f xs
instance FFoldable (NP xs) where
ffoldMap _ Nil = Mon.mempty
ffoldMap f (x :* xs) = mappend (f x) (ffoldMap f xs)
flengthAcc !acc Nil = acc
flengthAcc !acc (_ :* xs) = flengthAcc acc xs
instance FTraversable (NP xs) where
ftraverse _ Nil = A.pure Nil
ftraverse f (x :* xs) = liftA2 (:*) (f x) (ftraverse f xs)
-------------------------------------------------------------------------------
-- Apply
-------------------------------------------------------------------------------
class FFunctor t => FApply t where
fliftA2 :: (forall x. f x -> g x -> h x) -> t f -> t g -> t h
instance FApply (NP xs) where
fliftA2 _ Nil Nil = Nil
fliftA2 f (x :* xs) (y :* ys) = f x y :* fliftA2 f xs ys
instance FApply (Element a) where
fliftA2 f (Element x) (Element y) = Element (f x y)
instance FApply (NT f) where
fliftA2 f (NT g) (NT h) = NT $ \x -> f (g x) (h x)
instance FApply Limit where
fliftA2 f (Limit x) (Limit y) = Limit (f x y)
-------------------------------------------------------------------------------
-- Applicative
-------------------------------------------------------------------------------
class FApply t => FApplicative t where
fpure :: (forall x. f x) -> t f
instance FApplicativeNP xs => FApplicative (NP xs) where
fpure = fpureNP
class FApplicativeNP xs where
fpureNP :: (forall x. f x) -> NP xs f
instance FApplicativeNP '[] where
fpureNP _ = Nil
instance FApplicativeNP xs => FApplicativeNP (x ': xs) where
fpureNP x = x :* fpureNP x
instance FApplicative (Element a) where
fpure x = Element x
instance FApplicative (NT f) where
fpure x = NT $ \_ -> x
instance FApplicative Limit where
fpure x = Limit x
-------------------------------------------------------------------------------
-- Dicts, or what should be a better name?
-------------------------------------------------------------------------------
-- | Dfferent dictionary, not the same as in @constraints@
data Dict c a where
Dict :: c a => Dict c a
-- | TODO: what should be the superclass?
class FFunctor t => Dicts c t where
dicts :: t (Dict c)
instance DictsNP c xs => Dicts c (NP xs) where
dicts = dictsNP
class DictsNP c xs where
dictsNP :: NP xs (Dict c)
instance DictsNP c '[] where
dictsNP = Nil
instance (c x, DictsNP c xs) => DictsNP c (x ': xs) where
dictsNP = Dict :* dictsNP
instance c x => Dicts c (Element x) where
dicts = Element Dict
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
main :: IO ()
main = return ()