Search code examples
f#algebraic-data-typesfparsec

How to extract an FParsec result value to a variable in FSI


I'm using FParsec and trying to bind the resulting value to a variable in FSI. I tried with the following:

        > run pint32 "3";; // succeeds
        val it : ParserResult<int32,unit> = Success: 3
        > let x = run pint32 "3";; 
        val x : ParserResult<int32,unit> = Success: 3
        > x;;  // I bind the result to x
        val it : ParserResult<int32,unit> = Success: 3
        > let Success(y, _, _) = x;;  //It looks like I can extract the value...
        val Success : y:'a * 'b * 'c -> ParserResult<int32,unit>
        > y;;
        ...error FS0039: The value or constructor 'y' is not defined

It seems to bind and then forget it, but I assume I'm missing something, because the following destructuring works:

> type AB = A of int | B
let aa = A 1
let A a = aa;;

type AB =
  | A of int
  | B
val aa : AB = A 1
val A : a:'a -> AB
> a;;
val it : int = 1

And the following function seems able to extract the value using a match statement (though I'd need to change the failure type depending on the parser):

> let extract p str =
        match run p str with
        | Success(result, _, _)   -> result
        | Failure(errorMsg, _, _) -> 3
let z = extract pint32 "3"
z;;

val extract : p:Parser<int,unit> -> str:string -> int
val z : int = 3
val it : int = 3

What am I misunderstanding?


Solution

  • You're hitting the same problem as in this recent question:

    F#: Destructuring bind with a discriminated union

    Your let Success(y, _, _) = x line is actually creating a function named Success that takes a single 3-tuple as a parameter. What you need to do is let (Success(y, _, _)) = x.