On Tue, Oct 18, 2005 at 05:51:13PM +0100, Conor McBride wrote:
| Neither Oleg nor Bruno translated my code; they threw away my 
| structurally recursive on-the-fly automaton and wrote combinator parsers 
| instead. That's why there's no existential, etc. The suggestion that 
| removing the GADT simplifies the code would be better substantiated if 
| like was compared with like.

Here's a version in H98 + existentials.  I'm not claiming it proves
anything.

> module RegExp where

> import Control.Monad

> data RegExp tok a
>       = Zero
>       | One a
>       | Check (tok -> a) (tok -> Bool)
>       | Plus (RegExp tok a) (RegExp tok a)
>       | forall b. Mult (RegExp tok (b -> a)) (RegExp tok b)
>       | forall e. Star ([e] -> a) (RegExp tok e)

I could just use Prod (One f) instead of fmap f, but the functor
instance is mechanical:

> instance Functor (RegExp tok) where
>       fmap f Zero = Zero
>       fmap f (One v) = One (f v)
>       fmap f (Check k p) = Check (f.k) p
>       fmap f (Plus r1 r2) = Plus (fmap f r1) (fmap f r2)
>       fmap f (Mult r1 r2) = Mult (fmap (f.) r1) r2
>       fmap f (Star k r) = Star (f.k) r

Constructors

> one :: RegExp tok ()
> one = One ()

> check :: (tok -> Bool) -> RegExp tok tok
> check = Check id

> plus :: RegExp tok a -> RegExp tok b -> RegExp tok (Either a b)
> plus r1 r2 = Plus (fmap Left r1) (fmap Right r2)

> mult :: RegExp tok a -> RegExp tok b -> RegExp tok (a,b)
> mult r1 r2 = Mult (fmap (,) r1) r2

> star :: RegExp tok a -> RegExp tok [a]
> star = Star id

Parsing

> parse :: RegExp tok a -> [tok] -> Maybe a
> parse r []       = empty r
> parse r (t : ts) = parse (divide t r) ts

> empty :: RegExp tok a -> Maybe a
> empty Zero            = mzero
> empty (One v)         = return v
> empty (Check _ _)     = mzero
> empty (Plus r1 r2)    = empty r1 `mplus` empty r2
> empty (Mult r1 r2)    = empty r1 `ap` empty r2
> empty (Star k _)      = return (k [])

> divide :: tok -> RegExp tok a -> RegExp tok a
> divide t Zero         = Zero
> divide t (One v)      = Zero
> divide t (Check k p)
>   | p t               = One (k t)
>   | otherwise         = Zero
> divide t (Plus r1 r2) = Plus (divide t r1) (divide t r2)
> divide t (Mult r1 r2) = case empty r1 of
>       Nothing -> Mult (divide t r1) r2
>       Just f  -> Plus (Mult (divide t r1) r2) (fmap f (divide t r2))
> divide t (Star k r)   = Mult (fmap k_cons (divide t r)) (Star id r)
>   where k_cons x xs = k (x:xs)

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to