Haskell - 尝试 Monad 实例 - 语法问题
Haskell - Attempting Monad instance - syntax issues
我有以下定义:
newtype Parser a = Parser { parse :: String -> [(a,String)] }
instance Functor Parser where
fmap g (Parser pa) = Parser { parse = \s -> [(g a,s') | (a,s') <- pa s] }
instance Applicative Parser where
pure x = Parser { parse = \s -> [(x,s)] }
(<*>) (Parser pg) (Parser pa) = Parser { parse = \s -> [(g a,s'') | (g,s') <- pg s, (a, s'') <- pa s'] }
instance Monad Parser where
return = pure
(>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
问题在于绑定运算符的实现。我不确定为什么会出现类型错误。我试图在与 (<*>)
相同的行上定义绑定运算符
错误是:
parser.hs:17:58: error:
• Couldn't match expected type ‘(a, String)’
with actual type ‘[(a, t0)]’
• In the pattern: [(a, s')]
In a stmt of a list comprehension: [(a, s')] <- (pa s)
In the expression:
[(b, s'') | [(a, s')] <- (pa s), [(b, s'')] <- (g a) s']
• Relevant bindings include
g :: a -> Parser b (bound at parser.hs:17:20)
pa :: String -> [(a, String)] (bound at parser.hs:17:16)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(bound at parser.hs:17:2)
|
17 | (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
| ^^^^^^^^^
parser.hs:17:92: error:
• Couldn't match expected type ‘t0 -> [[(b, String)]]’
with actual type ‘Parser b’
• The function ‘g’ is applied to two arguments,
but its type ‘a -> Parser b’ has only one
In the expression: (g a) s'
In a stmt of a list comprehension: [(b, s'')] <- (g a) s'
• Relevant bindings include
s' :: t0 (bound at parser.hs:17:63)
g :: a -> Parser b (bound at parser.hs:17:20)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(bound at parser.hs:17:2)
|
17 | (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
更新:
为了完整起见,基于答案。这是有效的方法:
instance Monad Parser where
return = pure
(>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | (a, s') <- (pa s), (b,s'') <- parse (g a) s'] }
像 [(a, s')] <- (pa s)
这样的守卫模式意味着您期望 pa s
到 return 列表列表,每个列表恰好一对 a
和 s
在其中,而实际上 return 只是一个列表,其中包含任意数量的这些对。
基本上,去掉括号(以及来自其他绑定的)然后它应该可以工作。
我有以下定义:
newtype Parser a = Parser { parse :: String -> [(a,String)] }
instance Functor Parser where
fmap g (Parser pa) = Parser { parse = \s -> [(g a,s') | (a,s') <- pa s] }
instance Applicative Parser where
pure x = Parser { parse = \s -> [(x,s)] }
(<*>) (Parser pg) (Parser pa) = Parser { parse = \s -> [(g a,s'') | (g,s') <- pg s, (a, s'') <- pa s'] }
instance Monad Parser where
return = pure
(>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
问题在于绑定运算符的实现。我不确定为什么会出现类型错误。我试图在与 (<*>)
相同的行上定义绑定运算符错误是:
parser.hs:17:58: error:
• Couldn't match expected type ‘(a, String)’
with actual type ‘[(a, t0)]’
• In the pattern: [(a, s')]
In a stmt of a list comprehension: [(a, s')] <- (pa s)
In the expression:
[(b, s'') | [(a, s')] <- (pa s), [(b, s'')] <- (g a) s']
• Relevant bindings include
g :: a -> Parser b (bound at parser.hs:17:20)
pa :: String -> [(a, String)] (bound at parser.hs:17:16)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(bound at parser.hs:17:2)
|
17 | (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
| ^^^^^^^^^
parser.hs:17:92: error:
• Couldn't match expected type ‘t0 -> [[(b, String)]]’
with actual type ‘Parser b’
• The function ‘g’ is applied to two arguments,
but its type ‘a -> Parser b’ has only one
In the expression: (g a) s'
In a stmt of a list comprehension: [(b, s'')] <- (g a) s'
• Relevant bindings include
s' :: t0 (bound at parser.hs:17:63)
g :: a -> Parser b (bound at parser.hs:17:20)
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(bound at parser.hs:17:2)
|
17 | (>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | [(a, s')] <- (pa s), [(b,s'')] <- (g a) s'] }
更新: 为了完整起见,基于答案。这是有效的方法:
instance Monad Parser where
return = pure
(>>=) (Parser pa) g = Parser { parse = \s -> [(b,s'') | (a, s') <- (pa s), (b,s'') <- parse (g a) s'] }
像 [(a, s')] <- (pa s)
这样的守卫模式意味着您期望 pa s
到 return 列表列表,每个列表恰好一对 a
和 s
在其中,而实际上 return 只是一个列表,其中包含任意数量的这些对。
基本上,去掉括号(以及来自其他绑定的)然后它应该可以工作。