haskell - Using functional dependency to eliminate type parameter -
i trying implement parsec stream wrapper remember last uncons'd token in order provide look-behind capability. want wrapper work stream instance. here's have far:
{-# language flexibleinstances, multiparamtypeclasses #-} module mstream import text.parsec import control.monad ( liftm ) data mstream s t = mstream (maybe t) s instance stream s m t => stream (mstream s t) m t uncons (mstream _ s) = fmap (\(t, s') -> (t, mstream (just t) s')) `liftm` uncons s getprevtoken :: stream s m t => parsect (mstream s t) u m (maybe t) getprevtoken = (\(mstream t _) -> t) `liftm` getinput mstream :: s -> mstream s t mstream = mstream nothing this works, don't having carry t parameter in mstream type constructor. surely should sufficient require s parameter, since t can derived s long there witness stream s m t. i've tried using type families , gadts, keep running obscure errors ambiguous type variables , unsatisfied functional dependencies.
is there way remove t mstream type constructor don't have write:
sillyparser :: stream s m char => parsect (mstream s char) u m string sillyparser = t <- getprevtoken maybe (string "first") (\c -> string $ "last" ++ [c]) t
with
{-# language functionaldependencies #-} {-# language existentialquantification #-} {-# language flexibleinstances #-} {-# language undecidableinstances #-} module mstream import control.monad ( liftm ) -- class don't need carry `m` in `mstream` definition. class streamdep s t | s -> t class streamdep s t => stream s m t uncons :: s -> m (maybe (t, s)) data mstream s = forall t. streamdep s t => mstream (maybe t) s data parsect s u m = parsect s u (m a) instance monad m => monad (parsect s u m) getinput :: parsect s u m s getinput = undefined instance streamdep s t => streamdep (mstream s) t instance (monad m, stream s m t) => stream (mstream s) m t uncons (mstream _ s) = fmap (\(t, s') -> (t, mstream (just t) s')) `liftm` uncons s getprevtoken :: (monad m, stream s m t) => parsect (mstream s) u m (maybe t) getprevtoken = (\(mstream t _) -> t) `liftm` getinput mstream :: streamdep s t => s -> mstream s i quite close, error:
pars.hs:28:35: not deduce (t1 ~ t) context (monad m, stream s m t) bound type signature getprevtoken :: (monad m, stream s m t) => parsect (mstream s) u m (maybe t) @ pars.hs:27:17-76 or (streamdep s t1) bound pattern constructor mstream :: forall s t. streamdep s t => maybe t -> s -> mstream s, in lambda abstraction yet using both contexts stream s m t , streamdep s t1 should obvious (t ~ t1).
by using artillery, can make compile:
getprevtoken :: (monad m, stream s m t) => parsect (mstream s) u m (maybe t) getprevtoken = (\(mstream t _) -> unsafecoerce t) `liftm` getinput but cannot try this, requires modification parsec.
Comments
Post a Comment