[英]Haskell pattern matching inside of case
我试图在case子句内执行模式匹配:
-- different types of Parsers:
-- type Parser = String -> Maybe (String, String)
-- type Parser = String -> Maybe (Tree, String)
-- type Parser = String -> Maybe (Int, String)
-- can be generalized as:
data Parser a = Parser (String -> Maybe (a, String))
class Monad' m where
result :: a -> m a
bind :: m a -> (a -> m b) -> m b
instance Monad' Parser where
result v = Parser (\input -> Just (v, input))
bind (Parser fa) fb = Parser (\input ->
case (fa input) of
Nothing -> Nothing
Just(v, input') -> pb input' where pb in fb v = (Parser pb)
)
问题在于where pb in fb v = (Parser pb)
。 如何通过调用(fb input')声明pb然后模式匹配。
还需要在声明中包含构造函数Parser
: data Parser a = Parser (String -> Maybe (a, String))
似乎使事情复杂化很多。 它可以更简单地编写: data Parser a = String -> Maybe (a, String)
,但这是不可能有其他方法来实现这一点?
您可以使用let
或where
在任何允许这些表达式的位置创建模式匹配:(缩短一些行以使其适合StackOverflow的格式)
instance Monad' Parser where
result v = Parser (\input -> Just (v, input))
bind (Parser fa) fb =
Parser (\input -> case (fa input) of
Nothing -> Nothing
Just(v, input') -> pb input'
where (Parser pb) = fb v
)
=或=
instance Monad' Parser where
result v = Parser (\input -> Just (v, input))
bind (Parser fa) fb =
Parser (\input -> case (fa input) of
Nothing -> Nothing
Just(v, input') ->
let (Parser pb) = fb v
in pb input'
)
Haskell 98不允许类型同义词的实例声明。 GHC宣传了一种语言扩展,允许这样做,但我的经验是它导致了更深层次的问题。
解决模式匹配需求的标准方法是创建记录并使用该字段去除构造函数。 惯例似乎是使用un
++类型的名称。
data Parser a = Parser { unParser :: (String -> Maybe (a, String))}
-- N.B. unParser :: Parser a -> String -> Maybe (a, String)
instance Monad' Parser where
result v = Parser (\input -> Just (v, input))
bind (Parser fa) fb =
Parser (\input -> case (fa input) of
Nothing -> Nothing
Just(v, input') -> unParser (fb v) input
)
你没问的问题
你知道吗, Maybe
是Monad
? 当你发现自己编写了很多额外的代码来传播Nothing -> Nothing
,忽略失败并让Monad(或Applicative)实例成为你的朋友真的很棒。
instance Monad' Parser where
result v = Parser (\input -> Just (v, input))
bind (Parser fa) fb =
Parser (\input -> do -- This is in the Maybe Monad.
-- If any step fails the result is Nothing
(v, input') <- fa input
unParser (fb v) input'
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.