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
~
是类型相等约束,MonadParsec
和 Token
类型类由 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
我不明白(例如)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
~
是类型相等约束,MonadParsec
和 Token
类型类由 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