Filip Allberg
Filip Allberg

Reputation: 5191

Parsec: intuit type from parsed string

Is it possible to infer the type from 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"]

In the above example, I'd like for the weight parameter to get outputted as an Int, but this does not type-check.

Would it be wiser to represent a vertex as (String, String) and define parsers for the weight?

Upvotes: 0

Views: 42

Answers (1)

Cactus
Cactus

Reputation: 27626

The type Parser (Vertex a) is shorthand for forall a. Parser (Vertex a), i.e. its type states that for any choice of a, it can have type Parser (Vertex a). This is clearly not what you want: you want to say that parseVertex will always have type Parser (Vertex a) for some choice of a, but this choice is to be made by parseVertex, not at its call site.

What you should do, is use a type T such that Parser (Vertex T) covers all possible return values of parseVertex. For example, if you use Parser (Vertex (Either Int String)), then parseVertex can choose based on the parse results so far if it will return something of the form (s, Left x), or (s, Right t), where s :: String, x :: Int and t :: String.

Of course, that also means that consumers of parseVector now have to be able to handle both cases.

Upvotes: 1

Related Questions