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

megaparsec: how to declare the type of `eol` to parse Text and not [Char]

我不明白(例如)eol 的类型是什么意思:

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

或者,更好的是,我不明白如何将 eol 与 Text.Megaparsec.Text 一起使用,而不是 Text.Megaparsec.String

我一直在尝试学习如何使用 Megaparsec,遵循来自 Real World 的 Parsec 的(旧)教程 Haskell(实际上,在发现 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)"

类型中:

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

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

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

因此,完整类型可以解释为:eol 是一个具有 "return value" String 的单子解析器,它解析一个标记为 Char 的流。

对于你的问题,大部分可以忽略。您 运行 遇到的问题是 eol return 作为解析结果的 String 值,而 String 不是 Text,所以你不能使 eol(属于 Parser String 类型)成为 Parser Text 类型,无论你多么努力。

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

Data.Text.pack <$> eol