AspectAG-0.5.0.0: examples/List.hs
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE
TypeFamilies,
FlexibleContexts,
ScopedTypeVariables,
NoMonomorphismRestriction,
ImplicitParams,
ExtendedDefaultRules,
UnicodeSyntax,
DataKinds,
TypeApplications,
PartialTypeSignatures,
AllowAmbiguousTypes,
RankNTypes,
ScopedTypeVariables
#-}
module List where
import Prelude hiding (head, tail, sum, all, length, null, last)
import Language.Grammars.AspectAG
import Control.Monad
import Control.Applicative
import Data.Proxy
import GHC.TypeLits
type Nt_List = 'NT "List"
list = Label @ Nt_List
type P_Cons = 'Prd "Cons" Nt_List
cons = Label @ P_Cons
type P_Nil = 'Prd "Nil" Nt_List
nil = Label @ P_Nil
head :: forall a . Label ('Chi "head" P_Cons ('Right ('T a)))
head = Label
tail = Label @ ('Chi "tail" P_Cons ('Left Nt_List))
nilCh :: Label ('Chi "nilCh" P_Nil ('Right ('T ())))
nilCh = Label
-- data List a = Cons a (List a) | Nil () deriving Show
sem_List (proxy :: Proxy a) asp (x:xs)
= knitAspect cons asp
$ head @ a .=. sem_Lit @ a x
.*. tail .=. sem_List proxy asp xs
.*. EmptyRec
sem_List (_ :: Proxy a) asp []
= knitAspect nil asp
$ nilCh .=. sem_Lit () .*. EmptyRec
scata :: forall b . Label ('Att "cata" b)
scata = Label
asp_cata (Proxy :: Proxy a) f e
= (syndefM (scata @ a) cons $ f <$> ter head <*> at tail (scata @ a))
.+: (syndefM (scata @ a) nil $ pure e)
.+: emptyAspect
sum :: [Integer] -> Integer
sum xs
= sem_List (Proxy @ Integer)
(asp_cata (Proxy @ Integer) (+) 0) xs emptyAtt #. (scata @ Integer)
all xs
= sem_List (Proxy @ Bool)
(asp_cata (Proxy @ Bool) (&&) True) xs emptyAtt #. (scata @ Bool)
cata :: (a -> b -> b) -> b -> [a] -> b
cata (f :: a -> b -> b) e xs
= sem_List (Proxy @ a) (asp_cata (Proxy @ b) f e) xs emptyAtt #. (scata @ b)
tyApp :: (forall a. Label ('Att "cata" a)) -> Proxy a
-> (Label ('Att "cata" a))
tyApp poly (Proxy :: Proxy a) = poly @ a
slen = Label @ ('Att "slen" Integer)
asp_slen
= syndefM slen cons ((1+) <$> at tail slen)
.+: syndefM slen nil (pure 0) .+: emptyAspect
length xs
= sem_List (proxyFrom xs) asp_slen xs emptyAtt #. slen
sempty = Label @ ('Att "sempty" Bool)
asp_sempty
= syndefM sempty cons (pure False) .+: syndefM sempty nil (pure True) .+: emptyAspect
null xs = sem_List (proxyFrom xs) asp_sempty xs emptyAtt #. sempty
sid :: forall a . Label ('Att "sid" [a]) ; sid = Label
asp_sid
= \(Proxy :: Proxy a)
-> syndefM (sid @ a) cons ((:) <$> ter head <*> at tail sid)
.+: syndefM (sid @ a) nil (pure []) .+: emptyAspect
idList (xs :: [a])
= sem_List (proxyFrom xs) (asp_sid (proxyFrom xs)) xs emptyAtt #. (sid @ a) -- TODO
-- Si queremos evitar anotar tipos, los atributos polimorficos pueden tomar un proxy como
-- parametro, y usar proxyFrom
slast :: forall a . Label ('Att "slast" a); slast = Label
asp_slast (Proxy :: Proxy a)
= syndefM (slast @ a) cons (
do isLast <- at tail sempty
case isLast of
True -> ter head
False -> at tail slast
)
.+: syndefM (slast @ a) nil (error "Exception: empty list")
.+: emptyAspect
last (xs :: [a])
= sem_List (proxyFrom xs) (asp_slast (proxyFrom xs) .:+: asp_sempty)
xs emptyAtt #. slast @ a