使用 >>= 表示基本数字解析器
Expressing basic number parser using >>=
我正在阅读 WikiBook“在 48 小时内为自己编写一个方案”。
Haskell 库 Parsec 用于解析基本表达式,例如数字(如下面的代码所示)。
import Lib
import Text.ParserCombinators.Parsec hiding (spaces)
import System.Environment
import Control.Monad
import Data.Typeable ( typeOf )
import Debug.Trace
data LispVal = Atom String
| List [LispVal]
| DottedList [LispVal] LispVal
| Number Integer
| String String
| Bool Bool
deriving Show
-- ...
parseNumber :: Parser LispVal
parseNumber = do
x <- many1 digit
return $ Number (read x)
书中的一个练习要求 reader 使用 >>=
符号重写 parseNumber
。但是,我将 运行 保留为看起来很可怕的类型不匹配错误。有人可以告诉我如何使用 >>=
符号重写函数吗?或者至少给我一个提示?
Haskell 报告中有一节是关于 do notation 以及如何“脱糖”这些 do
块。
如果将 do
块写为:
parseNumber = do
x <- many1 digit
return (Number (read x))
那么这在语法上等同于:
parseNumber :: Parser LispVal
parseNumber = many1 digit >>= \x -> return (Number (read x))
或更优雅:
parseNumber :: Parser LispVal
parseNumber = many1 digit >>= return . Number . read
然而,我们不需要使用 >>=
。实际上,如果我们想在将使用 Parser
构造的项目上应用一个函数,那么我们可以为此使用 fmap :: Functor f => (a -> b) -> f a -> f b
or (<$>) :: Functor f => (a -> b) -> f a -> f b
:
parseNumber :: Parser LispVal
parseNumber = Number . read <$> many1 digit
我正在阅读 WikiBook“在 48 小时内为自己编写一个方案”。
Haskell 库 Parsec 用于解析基本表达式,例如数字(如下面的代码所示)。
import Lib
import Text.ParserCombinators.Parsec hiding (spaces)
import System.Environment
import Control.Monad
import Data.Typeable ( typeOf )
import Debug.Trace
data LispVal = Atom String
| List [LispVal]
| DottedList [LispVal] LispVal
| Number Integer
| String String
| Bool Bool
deriving Show
-- ...
parseNumber :: Parser LispVal
parseNumber = do
x <- many1 digit
return $ Number (read x)
书中的一个练习要求 reader 使用 >>=
符号重写 parseNumber
。但是,我将 运行 保留为看起来很可怕的类型不匹配错误。有人可以告诉我如何使用 >>=
符号重写函数吗?或者至少给我一个提示?
Haskell 报告中有一节是关于 do notation 以及如何“脱糖”这些 do
块。
如果将 do
块写为:
parseNumber = do
x <- many1 digit
return (Number (read x))
那么这在语法上等同于:
parseNumber :: Parser LispVal
parseNumber = many1 digit >>= \x -> return (Number (read x))
或更优雅:
parseNumber :: Parser LispVal
parseNumber = many1 digit >>= return . Number . read
然而,我们不需要使用 >>=
。实际上,如果我们想在将使用 Parser
构造的项目上应用一个函数,那么我们可以为此使用 fmap :: Functor f => (a -> b) -> f a -> f b
or (<$>) :: Functor f => (a -> b) -> f a -> f b
:
parseNumber :: Parser LispVal
parseNumber = Number . read <$> many1 digit