Parsec:来自已解析字符串的直觉类型

Parsec: intuit type from parsed string

是否可以从 many1 推断类型?

MWE

module Main where

import System.Environment (getArgs)
import Text.ParserCombinators.Parsec
import Data.Either (rights)

type Vertex vertexWeight = (String, vertexWeight)

parseVertex :: Parser (Vertex a)
parseVertex = do
  name <- many1 (noneOf "/")
  char '/'
  weight <- many1 (noneOf "\n")
  return $ (name, weight)

main :: IO ()
main = do
     putStrLn $ rights $ [parse parseVertex "test" "a/2"]

在上面的示例中,我希望 weight 参数作为 Int 输出,但这不会进行类型检查。

将顶点表示为 (String, String) 并为权重定义解析器是否更明智?

类型 Parser (Vertex a) 对于 forall a. Parser (Vertex a) 是 shorthand,即它的类型声明对于 any 选择 a,它的类型可以是 Parser (Vertex a)。这显然不是你想要的:你想说 parseVertex 对于 asome 选择总是有类型 Parser (Vertex a),但是这个选择由 parseVertex 制作,而不是在其调用站点制作。

你应该做的是使用类型 T 使得 Parser (Vertex T) 涵盖 parseVertex 的所有可能的 return 值。例如,如果您使用 Parser (Vertex (Either Int String)),那么 parseVertex 可以根据目前的解析结果来选择它是 return (s, Left x) 形式的东西,还是 (s, Right t) ],其中 s :: Stringx :: Intt :: String

当然,这也意味着 parseVector 的消费者现在必须能够处理这两种情况。