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

Popular posts from this blog

php - Zend Framework / Skeleton-Application / Composer install issue -

c# - Better 64-bit byte array hash -

python - PyCharm Type error Message -