megaparsec:如何声明`eol`的类型来解析Text而不是[Char]

时间:2017-06-21 16:19:09

标签: haskell types megaparsec

我无法理解(例如)eol的类型是什么意思:

eol :: (MonadParsec e s m, Token s ~ Char) => m String

或者,更好的是,我不明白如何在Text.Megaparsec.Text而不是Text.Megaparsec.String中使用eol。

我一直在尝试使用学习如何使用Megaparsec跟随来自Real World Haskell的Parsec的(旧)教程(我实际上在发现Megaparsec存在之前就开始阅读RWH教程)。我重写了code of the first example以使用Megaparsec(见下文)。但我发现当我尝试将eol的类型强制为Parser Text时,编译器会抛出错误:Couldn't match type ‘[Char]’ with ‘Text’,我从中收集到的是我无法使用eol使用Text,或者更有可能的是,我不知道如何从Token s ~ Char声明中更改eol上下文以使用Token Text

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

module CSVParser (
  module CSVParser
) where

import Foundation
import Data.Functor.Identity (Identity)
import Text.Megaparsec
import Text.Megaparsec.Text
import Data.Text

csvFile :: Parser [[Text]]
csvFile =
    do result <- many line
       eof
       return result

line :: Parser [Text]
line =
    do result <- cells
       --eol :: Parser Text -- uncommenting this line results in a compilation error
       eol
       return result

cells :: Parser [Text]
cells =
    do first <- cellContent
       next <- remainingCells
       return (first : next)

remainingCells =
    (char ',' >> cells)
    <|> return []

cellContent :: Parser Text
cellContent = fromList <$> many (noneOf [',','\n'])

parseCSV :: Text -> Either (ParseError (Token Text) Dec) [[Text]]
parseCSV = parse csvFile "(unknown)"

1 个答案:

答案 0 :(得分:4)

在类型中:

eol :: (MonadParsec e s m, Token s ~ Char) => m String

~是类型相等约束,MonadParsecToken类型类由Megaparsec定义。它们大致可以解释如下:

  • MonadParsec e s m是一个断言,类型m是一个monadic解析器,它读取Stream类型s并使用类型ErrorComponent表示错误{1}}
  • e是从流Token s
  • 读取的令牌的基础类型

因此,完整类型可以解释为:s是一个具有“返回值”eol的monadic解析器,用于解析其标记为String的流。

对于您的问题,大部分内容都可以忽略。您遇到的问题是,Char作为解析结果返回eol值,而String不是String,因此您可以' t Text eol类型Parser String类型Parser Text,无论你怎么努力。

两种解决方案是忽略不需要的String返回值,或者,如果您需要它作为文本,请将其转换为:

Data.Text.pack <$> eol