@@ -1,263 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE TupleSections #-}
3−{-# LANGUAGE FlexibleContexts #-}
4−{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE DefaultSignatures #-}
6−{-# LANGUAGE OverloadedStrings #-}
7−{-# LANGUAGE MultiParamTypeClasses #-}
8−{-# LANGUAGE FunctionalDependencies #-}
11−import Prelude hiding (id, (.), take, takeWhile)
13−import Control.Applicative
15−import Control.Category
16−import Control.Lens hiding (imap, _Cons)
18−import qualified Data.Attoparsec.Text as Text
19−import Data.Attoparsec.Types
21−import Data.Functor.Identity
22−import Data.MonoTraversable
23−import Data.Sequences hiding (take, takeWhile)
24−import Data.Text (Text)
30−-- | Isomorphism in the kleisli category of some monad.
31−data KleisliIso m a b = KleisliIso (Kleisli m a b) (Kleisli m b a)
33−instance Monad m => Category (KleisliIso m) where
34− id = KleisliIso id id
35− (KleisliIso f g) . (KleisliIso f' g') = KleisliIso (f . f') (g' . g)
37−isoK :: (a -> m b) -> (b -> m a) -> KleisliIso m a b
38−isoK f g = KleisliIso (Kleisli f) (Kleisli g)
40−apply :: KleisliIso m a b -> a -> m b
41−apply (KleisliIso (Kleisli f) _) = f
43−unapply :: KleisliIso m a b -> b -> m a
44−unapply (KleisliIso _ (Kleisli g)) = g
46−from :: KleisliIso m a b -> KleisliIso m b a
47−from (KleisliIso f g) = KleisliIso g f
49−unit :: Monad m => KleisliIso m (a, ()) a
50−unit = isoK (return . fst) (return . (, ()))
52−symmetry :: Monad m => KleisliIso m (a, b) (b, a)
54− where f (a, b) = return (b, a)
56−equalTo :: (Eq a, Monad m) => a -> KleisliIso m a ()
59− f y | x == y = return ()
60− | otherwise = fail "equalTo: not equal"
63−oneWayConst :: Monad m => a -> KleisliIso m a ()
64−oneWayConst x = isoK f g
69−check :: Monad m => (a -> Bool) -> KleisliIso m a a
71− where f x | p x = return x
72− | otherwise = fail "check: predicate failed"
74−packed :: (Monad m, IsSequence seq) => KleisliIso m [Element seq] seq
75−packed = isoK (return . fromList) (return . otoList)
77−-- | Isomorphism between unit and empty list.
78−_Nil :: Monad m => KleisliIso m () [a]
83− g _ = fail "expected empty list"
85−-- | Isomorphism between (head, tail) and a non empty list.
86−_Cons :: Monad m => KleisliIso m (a, [a]) [a]
89− f (x, xs) = return (x:xs)
90− g (x:xs) = return (x, xs)
91− g _ = fail "expected non-empty list"
93−-- | A functor from the category of isomorphisms of the Kleisli category
94−-- of some monad to Hask.
95−class IsoFunctor f where
96− imap :: KleisliIso Identity a b -> f a -> f b
97− imapK :: KleisliIso m a b -> f a -> f (m b)
99−(/$/) :: IsoFunctor f => KleisliIso Identity a b -> f a -> f b
102−class IsoFunctor f => IsoPointed f where
106− ipure :: KleisliIso Identity () a -> f a
109− ipureK :: KleisliIso m () a -> f (m a)
110− ipureK = (`imapK` iunit)
112− {-# MINIMAL iunit | ipure #-}
114−class IsoFunctor f => IsoFail f where
115− ifail :: String -> f a
117−class IsoPointed f => IsoApply f where
118− (/*/) :: f a -> f b -> f (a, b)
120− (/*) :: f a -> f () -> f a
121− f /* g = unit /$/ f /*/ g
123− (*/) :: f () -> f b -> f b
124− f */ g = unit . symmetry /$/ f /*/ g
126− {-# MINIMAL (/*/) #-}
128−class IsoApply f => IsoAlternative f where
130− (/|/) :: f a -> f a -> f a
132− isome :: f a -> f [a]
133− isome v = _Cons /$/ v /*/ imany v
135− imany :: f a -> f [a]
136− imany v = isome v /|/ ipure _Nil
138− sepBy :: f a -> f () -> f [a]
139− sepBy v s = sepBy1 v s /|/ ipure _Nil
141− sepBy1 :: f a -> f () -> f [a]
142− sepBy1 v s = _Cons /$/ v /* s /*/ sepBy v s
144− {-# MINIMAL iempty, (/|/) #-}
146−class (IsoAlternative syn, IsoFail syn) => Syntax syn seq | syn -> seq where
147− joinErr :: syn (Either String a) -> syn a
149− anyChar :: syn (Element seq)
151− char :: Element seq -> syn ()
152− default char :: Eq (Element seq) => Element seq -> syn ()
153− char c = equalTo c /$/ anyChar
155− satisfy :: (Element seq -> Bool) -> syn (Element seq)
156− satisfy p = joinErr (imapK (check p) anyChar)
158− string :: seq -> syn ()
159− default string :: (IsSequence seq, Eq seq) => seq -> syn ()
160− string s = equalTo s /$/ take (olength s)
162− take :: Int -> syn seq
163− default take :: IsSequence seq => Int -> syn seq
164− take n = packed /$/ ireplicate n anyChar
166− takeWhile :: (Element seq -> Bool) -> syn seq
167− default takeWhile :: IsSequence seq => (Element seq -> Bool) -> syn seq
168− takeWhile p = packed /$/ imany (satisfy p)
170− takeWhile1 :: (Element seq -> Bool) -> syn seq
171− default takeWhile1 :: IsSequence seq => (Element seq -> Bool) -> syn seq
172− takeWhile1 p = packed /$/ isome (satisfy p)
174− {-# MINIMAL joinErr, anyChar #-}
176−ireplicate :: IsoApply f => Int -> f a -> f [a]
177−ireplicate 0 _ = ipure _Nil
178−ireplicate n m = _Cons /$/ m /*/ ireplicate (n-1) m
180−isequence :: IsoApply f => [f a] -> f [a]
181−isequence [] = ipure _Nil
182−isequence (x:xs) = _Cons /$/ x /*/ isequence xs
184−skipSpace :: (Syntax syn seq, IsSequence seq, Element seq ~ Char) => syn ()
185−skipSpace = oneWayConst (fromList []) /$/ takeWhile isSpace
187−skipSpace1 :: (Syntax syn seq, IsSequence seq, Element seq ~ Char) => syn ()
188−skipSpace1 = oneWayConst (singleton ' ') /$/ takeWhile1 isSpace
190−-- Attoparsec implementation.
192−instance IsoFunctor (Parser i) where
193− imap i m = fmap (runIdentity . apply i) m
194− imapK i m = fmap (apply i) m
196−instance IsoFail (Parser i) where
199−instance IsoPointed (Parser i) where
200− ipure = pure . runIdentity . (`apply` ())
202−instance IsoApply (Parser i) where
203− f /*/ g = (,) <$> f <*> g
205−instance IsoAlternative (Parser i) where
211− sepBy1 = Text.sepBy1
213−instance Syntax (Parser Text) Text where
214− joinErr = (>>= either fail return)
215− anyChar = Text.anyChar
216− satisfy = Text.satisfy
217− char = void . Text.char
218− string = void . Text.string
219− takeWhile = Text.takeWhile
220− takeWhile1 = Text.takeWhile1
229−_Var :: Monad m => KleisliIso m Text AST
233− g (Var t) = return t
234− g _ = fail "expected a Var"
236−_App :: Monad m => KleisliIso m (AST, AST) AST
239− f = return . uncurry App
240− g (App h x) = return (h, x)
241− g _ = fail "expected an App"
243−_Abs :: Monad m => KleisliIso m (Text, AST) AST
246− f = return . uncurry Abs
247− g (Abs n b) = return (n, b)
248− g _ = fail "expected an Abs"
250−name :: Syntax syn Text => syn Text
251−name = takeWhile1 isAlphaNum
253−atom :: Syntax syn Text => syn AST
255− /|/ char '(' */ expr /* char ')'
257−expr :: Syntax syn Text => syn AST
258−expr = _App /$/ atom /* skipSpace1 /*/ atom
259− /|/ _Abs /$/ char '\\' /* skipSpace
260− */ name /* skipSpace
261− /* string "->" /* skipSpace