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