【问题标题】:Program error: undefined member: >>= Haskell程序错误:未定义成员:>>= Haskell
【发布时间】:2018-12-12 14:42:01
【问题描述】:

我在 Haskell 中实现了一个简单的解释器,但我遇到了这个问题。代码是这样的:

import Control.Applicative
import Data.Char

newtype Parser a = P (String -> [(a,String)])

parse :: Parser a -> String -> [(a,String)]
parse (P p) inp = p inp

item :: Parser Char
item = P (\inp -> case inp of
    [] -> []
    (x:xs) -> [(x,xs)])

instance Functor Parser where
fmap :: (a -> b) -> Parser a -> Parser b
fmap g p = P (\inp -> case parse p inp of
    [] -> []
    [(v,out)] -> [(g v, out)])

instance Monad Parser where
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
p >>= f = P (\inp -> case parse p inp of
    [] -> []
    [(v,out)] -> parse (f v) out)

three :: Parser (Char,Char)
three = do {x <- item;
    item;
    z <- item;
    return (x,z);}

如果我在拥抱中运行脚本,一切似乎都很好。但是当我尝试运行命令时

parse three "abcdef"

我收到一个错误:

Program error: undefined member: >>=

请问有人可以帮我吗?

【问题讨论】:

    标签: parsing haskell monads sequencing


    【解决方案1】:
    1. 不要给实例类型签名。

    2. 缩进实例定义。

    在这两件事之后你会看到一个新的错误,你需要定义一个 Applicative 实例,因为class Applicative m =&gt; Monad m

    编辑:

    你写道:

    instance Monad Parser where
    (>>=) :: Parser a -> (a -> Parser b) -> Parser b    -- This is a type signature
    p >>= f = P (\inp -> case parse p inp of   -- This is the definition
        [] -> []
        [(v,out)] -> parse (f v) out)
    

    第一个问题是类型签名,我在上面的评论中指出了这一点。删除它:

    instance Monad Parser where
    p >>= f = P (\inp -> case parse p inp of   -- This is the definition
        [] -> []
        [(v,out)] -> parse (f v) out)
    

    第二个问题是缩进。您必须缩进成员函数定义(或使用花括号,但这是一种不常见的样式):

    instance Monad Parser where
        p >>= f = P (\inp -> case parse p inp of
           [] -> []
           [(v,out)] -> parse (f v) out)
    

    现在您收到一个新错误,提示您需要一个应用实例。所以你需要:

    instance Applicative Parser where
        pure = ...
        (<*>) = ...
    

    即使在那之后,它也会告诉你为 Functor 编写一个实例。

    【讨论】:

    • 我对这种语言很陌生。我试图理解“在haskell中编程”一书中描述的内容。你能举一个你所说的例子吗?
    • @paolopast 当然,请参阅我的编辑。如果没有告诉您编写 Applicative 和 Functor 实例,那么您正在关注的这本书可能已经过时了。
    • 我收到“表达式中的语法错误(意外的 `}',可能是由于布局错误)”。但是没有'}'
    • 我刚刚解决了。这是一个缩进的问题。但现在它告诉我实现返回函数。我会检查这本书。非常感谢!!
    • @Paolopast 是的,return 是将值“放入”您的 monad 的函数。在这种情况下,可能是return x = P $ \str -&gt; [(x, str)]。而且,您将需要具有相同定义的pure。 (pure == return)。
    【解决方案2】:

    在声明实例时不要显式地编写类型。但是,如果您真的想这样做,请转InstanceSigs 扩展名:{-# LANGUAGE InstanceSigs #-}

    正如另一个答案中提到的,Haskell 是缩进敏感的,但是您可以将定义放在括号中以绕过它:

    instance SomeClass Int where {
    x = 3
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多