packages feed

lambdabot-4.0: Plugin/Lambda/LangPack.hs

--
-- | Based on (ripping) ideas from 
--          /Language Prototyping using Modular Monadic Semantics/
--
module Plugin.Lambda.LangPack where

import Control.Monad.Error

import Data.Dynamic

newtype Fix f = In { out :: f (Fix f) }

fold :: (Functor f) => (f a -> a) -> Fix f -> a
fold phi = phi . fmap (fold phi) . out

(@@) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c
f @@ g = \x -> g x >>= f

mFold :: (MFunctor f m) => (f a -> m a) -> Fix f -> m a
mFold mPhi = mPhi @@ mMap (mFold mPhi) @@ (return . out)

class (Functor f, Monad m) => MFunctor f m where
    mMap :: (a -> m b) -> f a -> m (f b)

class Pause m r | m -> r where
    pause :: ((a -> r) -> r) -> m a

--------------------------------------------------------------------------------

{- bugger it, I'll just use Dynamics
-- Functional dependencies may help
-- Extensible sums (as seen in many places e.g.
--            "Monad Transformers and Modular Interpreters")
class Subtype sub sup where
    inj :: sub -> sup
    prj :: sup -> Maybe sub

instance Subtype a (Either a b) where
    inj = Left
    prj = either Just (const Nothing)

instance Subtype a b => Subtype a (Either c b) where
    inj = Right . inj
    prj = either (const Nothing) prj
-}

-- prj' :: (Subtype sub sup, MonadError String m) => m sup -> m sub
prj' :: (MonadError String m, Typeable a) => m Dynamic -> m a
prj' x = do x' <- x
            case {-trace (show x')-} prj x' of
               Nothing -> throwError "type error"
               Just xr -> return xr

inj :: (Typeable a) => a -> Dynamic
inj = toDyn

prj :: (Typeable a) => Dynamic -> Maybe a
prj = fromDynamic

newtype SumF f g x = S { unS :: Either (f x) (g x) }

instance (Functor f, Functor g) => Functor (SumF f g) where
    fmap f = S . either (Left . fmap f) (Right . fmap f) . unS

--------------------------------------------------------------------------------
-- More Labragayo, but with a some of my own concoctions
{-
class HasParser t where
    parser :: Parser t

class HasParserF f where
    parserF :: (f x -> x) -> Parser x -> Parser (f x)

instance (HasParserF f, HasParserF g) => HasParserF (SumF f g) where
    parserF up parser = fmap S $ try (fmap Left (parserF (up . S . Left) parser)) <|>
                                      fmap Right (parserF (up . S . Right) parser)

instance (HasParserF f) => HasParser (Fix f) where
    parser = fmap In (parserF In parser)
-}