1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE ConstraintKinds #-}
3 {-# LANGUAGE Rank2Types #-}
4 -- | Interpreter to duplicate the representation of an expression
5 -- in order to evaluate it with different interpreters.
7 -- NOTE: this is a more verbose, less clear,
8 -- and maybe less efficient alternative
9 -- to maintaining the universal polymorphism of @repr@
10 -- either using @NoMonomorphismRestriction@ when writing an EDSL,
11 -- or with a @forall repr.@ within a data type
12 -- when writing a DSL; as is done when parsing 'Term' in this library;
13 -- it is thus mainly here for the sake of curiosity.
14 module Language.Symantic.Interpreting.Dup where
16 import Control.Applicative (Applicative(..), Alternative(..))
17 import Data.Functor (Functor(..))
20 -- | Duplicate an implicitly generated representation.
22 -- Useful to combine two symantic interpreters into one.
23 data Dup repr1 repr2 a
29 instance (Functor x, Functor y) => Functor (Dup x y) where
30 fmap f (x`Dup`y) = fmap f x `Dup` fmap f y
31 instance (Applicative x, Applicative y) => Applicative (Dup x y) where
32 pure a = pure a `Dup` pure a
33 (f`Dup`g) <*> (x`Dup`y) = f <*> x `Dup` g <*> y
34 (f`Dup`g) <* (x`Dup`y) = f <* x `Dup` g <* y
35 (f`Dup`g) *> (x`Dup`y) = f *> x `Dup` g *> y
36 instance (Alternative x, Alternative y) => Alternative (Dup x y) where
37 empty = empty `Dup` empty
38 (f`Dup`g) <|> (x`Dup`y) = f <|> x `Dup` g <|> y
39 many (x`Dup`y) = many x `Dup` many y
40 some (x`Dup`y) = some x `Dup` some y
43 -- | To be used with the @TypeApplications@ language extension:
47 dup0 :: (cl x, cl y) => (forall repr. cl repr => repr a) -> Dup x y a
53 (forall repr. cl repr => repr a -> repr b) ->
54 Dup x y a -> Dup x y b
55 dup1 f (a1 `Dup` a2) =
61 (forall repr. cl repr => repr a -> repr b -> repr c) ->
62 Dup x y a -> Dup x y b -> Dup x y c
63 dup2 f (a1 `Dup` a2) (b1 `Dup` b2) =
69 (forall repr. cl repr => repr a -> repr b -> repr c -> repr d)
70 -> Dup x y a -> Dup x y b -> Dup x y c -> Dup x y d
71 dup3 f (a1 `Dup` a2) (b1 `Dup` b2) (c1 `Dup` c2) =
72 f a1 b1 c1 `Dup` f a2 b2 c2
75 dupList :: [Dup x y a] -> ([x a], [y a])
76 dupList = foldr (\(a`Dup`b) ~(as, bs) -> (a:as, b:bs)) ([],[])