Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何为一元语法分析器实现Monad、MonadError和MonadState,而不使用泛化的newtypedering扩展?_Haskell - Fatal编程技术网

Haskell 如何为一元语法分析器实现Monad、MonadError和MonadState,而不使用泛化的newtypedering扩展?

Haskell 如何为一元语法分析器实现Monad、MonadError和MonadState,而不使用泛化的newtypedering扩展?,haskell,Haskell,我在haskell中找到了一个使用一元错误处理和状态的解析器示例。 是这样写的 {-# LANGUAGE GeneralizedNewtypeDeriving #-} import Control.Monad.Except import Control.Monad.State newtype Parser a = Parser { runParser :: ExceptT String (State String) a } deriving ( Functor

我在haskell中找到了一个使用一元错误处理和状态的解析器示例。 是这样写的

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Monad.Except
import Control.Monad.State

newtype Parser a
  = Parser { runParser :: ExceptT String (State String) a }
    deriving ( Functor
             , Applicative
             , Monad
             , MonadError String
             , MonadState String
             )
我了解它的功能和使用方法。但是,我想知道的是如何 它的实现没有
GeneralizedNewtypeDeriving
扩展

那么,如何使
解析器
成为
函子
应用程序
单子
的实例,
MonadError
MonadState
如果没有
generalizednewtypedering

扩展名?

GeneralizedNewtypeDeriving
newtype
样板文件包装基础类型的实例(在您的示例中,
ExceptT String(State String)
)。例如,
函子
一等于:

-- p :: ExceptT String (State String) a
instance Functor Parser where
    fmap f (Parser p) = Parser (fmap f p)
    -- Or, equivalently:
    -- fmap f = Parser . fmap f . runParser
至于底层实例做什么,您可以通过以下文档中实例的“源”链接来检查它们的源,例如:

instance (Functor m) => Functor (ExceptT e m) where
    fmap f = ExceptT . fmap (fmap f) . runExceptT

(嵌套的
fmap
之所以存在,是因为
的底层类型除了ema
m(ea)
,因此有两个
Functor
层需要通过:
m
ear

泛化newtypederiving
包装底层类型的实例(在您的例子中,
除了字符串(状态字符串)
)和
newtype
样板。例如,
Functor
一等于:

-- p :: ExceptT String (State String) a
instance Functor Parser where
    fmap f (Parser p) = Parser (fmap f p)
    -- Or, equivalently:
    -- fmap f = Parser . fmap f . runParser
至于底层实例做什么,您可以通过以下文档中实例的“源”链接来检查它们的源。例如,is:

instance (Functor m) => Functor (ExceptT e m) where
    fmap f = ExceptT . fmap (fmap f) . runExceptT

(嵌套的
fmap
之所以存在,是因为
的基本类型除了ema
m(ea)
,因此有两个
Functor
层需要通过:
m
ear

我几乎花了一整天的时间才弄清楚如何实现它 弄明白了,这个概念其实很简单,关键是要挖掘 通过monad堆栈应用一个要实现的函数,然后 再次将结果埋在monad堆栈中。这些工作可以用这些 职能:

unwrap :: Parser a -> String -> (Either String a, String)
unwrap p s = runState (runExceptT (runParser p)) s

wrap :: (String -> (Either String a, String)) -> Parser a
wrap f = Parser (ExceptT (state (\s -> (f s))))
因此,要使解析器成为
Functor
Applicative
Monad
的实例,
MonadError
MonadState
我可以在其中定义lambda或函数
where
绑定,然后使用
wrap
将其包装

以下是实现的实例:

instance Functor Parser where
  fmap f p = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> (Right (f a), s')
                       Left  e -> (Left e, s)

instance Applicative Parser where
  pure x    = wrap fn
    where fn s = (Right x, s)

  p1 <*> p2 = wrap fn
    where fn s = let (ef, s')  = unwrap p1 s
                     (ea, s'') = unwrap p2 s'
                  in run ef ea s'' s

          run (Right f) (Right a) s' s = (Right (f a), s')
          run (Left  e) _         s' s = (Left e, s)
          run _         (Left e)  s' s = (Left e, s)

instance Monad Parser where
  return  = pure

  p >>= f = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> unwrap (f a) s'
                       Left  e -> (Left e, s)

instance MonadError String Parser where
  throwError err = wrap fn
    where fn s = (Left err, s)

  catchError p h = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> (Right a, s')
                       Left  e -> unwrap (h e) s

instance MonadState String Parser where
  get   = wrap fn
    where fn s = (Right s, s)

  put s = wrap fn
    where fn s = (Right (), s)
实例函子解析器,其中
fmap f p=包裹fn
其中fn s=let(ea,s')=展开s
如果ea
右a->(右(f a),s')
左e->(左e,s)
实例应用程序解析器,其中
纯x=包裹fn
其中fn s=(右x,s)
p1 p2=包裹fn
其中fn s=let(ef,s')=展开p1 s
(ea,s'')=展开p2'
在运行ef ea s时
运行(右f)(右a)s's=(右(f a),s')
运行(左e)s's=(左e,s)
运行(左e)s=(左e,s)
实例Monad解析器,其中
返回=纯
p>>=f=wrap fn
其中fn s=let(ea,s')=展开s
如果ea
右a->展开(f a)的
左e->(左e,s)
实例MonadError字符串解析器,其中
投掷者错误=包裹fn
其中fn s=(左错误,s)
捕捉错误p h=包裹fn
其中fn s=let(ea,s')=展开s
如果ea
右a->(右a,s')
左e->展开(h e)s
实例MonadState字符串解析器,其中
get=wrap fn
其中fn s=(右s,s)
放置s=包裹fn
其中fn s=(右(),s)
这样,现在就可以像这样使用解析器:

item :: Parser Char
item = do
  s <- get
  case s of
    []     -> throwError "unexpected end of input"
    (c:cs) -> do put cs
                 return c

satisfy :: (Char -> Bool) -> Parser Char
satisfy p = item >>= \c -> if p c then return c else throwError $ "unexpected: " ++ show c

char :: Char -> Parser Char
char c = satisfy (c ==)

main :: IO ()
main = do
  print $ unwrap item "c"
  print $ unwrap (char 'c') "c"
  print $ unwrap (satisfy isDigit) "c"
item::Parser Char
item=do
s Throwerr“输入意外结束”
(c:cs)->不要放cs
返回c
满足:(Char->Bool)->解析器Char
满足p=item>>=\c->如果p-c,则返回c-else-throwerr$“意外:”++显示c
char::char->Parser char
字符c=满足(c==)
main::IO()
main=do
打印$unwrap项目“c”
打印$unwrap(字符“c”)“c”
打印$unwrap(满足isDigit)“c”

我花了几乎一整天的时间才弄明白如何实现这一点 弄明白了,这个概念其实很简单,关键是要挖掘 通过monad堆栈应用一个要实现的函数,然后 再次将结果埋在monad堆栈中。这些工作可以用这些 职能:

unwrap :: Parser a -> String -> (Either String a, String)
unwrap p s = runState (runExceptT (runParser p)) s

wrap :: (String -> (Either String a, String)) -> Parser a
wrap f = Parser (ExceptT (state (\s -> (f s))))
因此,要使解析器成为
Functor
Applicative
Monad
的实例,
MonadError
MonadState
我可以在其中定义lambda或函数
where
绑定,然后使用
wrap
将其包装

以下是实现的实例:

instance Functor Parser where
  fmap f p = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> (Right (f a), s')
                       Left  e -> (Left e, s)

instance Applicative Parser where
  pure x    = wrap fn
    where fn s = (Right x, s)

  p1 <*> p2 = wrap fn
    where fn s = let (ef, s')  = unwrap p1 s
                     (ea, s'') = unwrap p2 s'
                  in run ef ea s'' s

          run (Right f) (Right a) s' s = (Right (f a), s')
          run (Left  e) _         s' s = (Left e, s)
          run _         (Left e)  s' s = (Left e, s)

instance Monad Parser where
  return  = pure

  p >>= f = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> unwrap (f a) s'
                       Left  e -> (Left e, s)

instance MonadError String Parser where
  throwError err = wrap fn
    where fn s = (Left err, s)

  catchError p h = wrap fn
    where fn s = let (ea, s') = unwrap p s
                  in case ea of
                       Right a -> (Right a, s')
                       Left  e -> unwrap (h e) s

instance MonadState String Parser where
  get   = wrap fn
    where fn s = (Right s, s)

  put s = wrap fn
    where fn s = (Right (), s)
实例函子解析器,其中
fmap f p=包裹fn
其中fn s=let(ea,s')=展开s
如果ea
右a->(右(f a),s')
左e->(左e,s)
实例应用程序解析器,其中
纯x=包裹fn
其中fn s=(右x,s)
p1 p2=包裹fn
其中fn s=let(ef,s')=展开p1 s
(ea,s'')=展开p2'
在运行ef ea s时
运行(右f)(右a)s's=(右(f a),s')
运行(左e)s's=(左e,s)
运行(左e)s=(左e,s)
实例Monad解析器,其中
返回=纯
p>>=f=wrap fn
其中fn s=let(ea,s')=展开s
如果ea
右a->展开(f a)的
左e->(左e,s)
实例MonadError字符串解析器,其中
投掷者错误=包裹fn
其中fn s=(左错误,s)