【问题标题】:Why does this haskell code failed为什么这个haskell代码失败
【发布时间】:2017-03-14 09:06:31
【问题描述】:

首先我并没有完全理解错误信息,所以我只能使用一个模棱两可的问题标题

这段代码来自第 9 频道关于 haskell 编程的讲座的第 8 章

我试图通过 GHC 运行这段代码,然后我写了

-- Functional parsing library from chapter 13 of Programming in Haskell,
-- Graham Hutton, Cambridge University Press, 2016.

module Parsing (module Parsing, module Control.Applicative) where
import Data.Typeable
import Control.Applicative
import Data.Char

-- Basic definitions

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)])

-- Sequencing parsers

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 Applicative Parser where
   -- pure :: a -> Parser a
   pure v = P (\inp -> [(v,inp)])

   -- <*> :: Parser (a -> b) -> Parser a -> Parser b
   pg <*> px = P (\inp -> case parse pg inp of
                             []        -> []
                             [(g,out)] -> parse (fmap g px) 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)

-- Making choices

instance Alternative Parser where
   -- empty :: Parser a
   empty = P (\inp -> [])

   -- (<|>) :: Parser a -> Parser a -> Parser a
   p <|> q = P (\inp -> case parse p inp of
                           []        -> parse q inp
                           [(v,out)] -> [(v,out)])

return' :: a -> Parser a
return' v = \inp -> [(v, inp)]

p' :: Parser (Char, Char)
p' = do 
    x <- item
    item
    y <- item
    return' (x, y)

main = print (p' "123")

代码包含我从给定的演示代码 Parsing.hs 中复制的大量代码,以及与幻灯片相同的 p' 函数

运行此代码会导致错误

4.hs:63:15: error:
? Couldn't match expected type ‘[Char] -> a0’
              with actual type ‘Parser (Char, Char)’
? The function ‘p'’ is applied to one argument,
  but its type ‘Parser (Char, Char)’ has none
  In the first argument of ‘print’, namely ‘(p' "123")’
  In the expression: print (p' "123")

类型好像有问题,我试过了

main = print (item "123")

也没有用

但是,当我简单地删除 Parser 的定义,并将它们替换为上一张幻灯片中提到的定义时

type Parser a = String -> [(a, String)]

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

return' :: a -> Parser a
return' v = \inp -> [(v, inp)]

main = print (item "123")

它只适用于输出[('1',"23")],我在这里感到困惑。

顺便说一句,我发现在评论部分有一个 leomm 和我问了同样的问题,他后来才明白这一点。但是我就是无法解决这个问题。

【问题讨论】:

  • itemParser。我认为你需要parse item "123" 而不仅仅是item "123"
  • p' 属于Parser (Char,Char) 类型,即newtype,因此它被视为与您期望的函数类型不同的类型,即使它与它同构。正如MathematicalOrchid 指出的那样,您可以使用parse p' 来恢复您想要的功能。

标签: haskell functional-programming monads


【解决方案1】:

newtype 需要构造函数,type 不需要。如果我们想用newtype 替换type,我们需要在Parser 类型的任何用法中添加一个构造函数,例如P;为了解析Parser,我们实现了parse

从你的第二个示例代码开始,我们将得到

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)])

main = print (parse item "12345")

现在让我们实现您的特殊解析器p。为了使用do,我们实现了 Monad 实例。

我们添加到我们的代码中:

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)
  -- return :: a -> Parser a
  return v = P (\inp -> [(v, inp)])

p :: Parser (Char, Char)
p = do  
  x <- item
  item
  y <- item
  return (x, y)

我们的main 命令变为:

main = print (parse p "12345")

在我看来,ghc 中的错误信息相当广泛,但必须非常仔细地阅读;使用数据类型时也必须非常小心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    相关资源
    最近更新 更多