Search code examples
typessmlsmlnjalgebraic-data-types

datatype and type in SML not working as intended


I am trying to implement a little parsing library based on a monadic parsing paper. I want to do it using SML(NJ), as I am learning about SML.

Here is what I have so far:

type 'a parse_data = ('a * char list);
type 'a parse_result = 'a parse_data list;

type 'a parser = char list -> 'a parse_data list;

datatype 'a parse_result = ParseFailure
                         | ParseSuccess of 'a parse_result;

Then I try to use it as follows:

ParseSuccess ([("a", [#"a"]), ("b", [#"b"])]: string parse_result);

Which gives the following error:

stdIn:21.15-21.66 Error: expression doesn't match constraint [tycon mismatch]
  expression: (string * char list) list
  constraint: string parse_result
  in expression:
    ("a",#"a" :: nil) :: ("b",#"b" :: nil) :: nil: string parse_result

I think this is weird, because I think I have aliased ('a * char list) list with 'a parse_result using the type declarations already. So I try to dig deeper into the issue and try the following:

([("a", [#"a"]), ("b", [#"b"])]: string parse_result);

Again error, now as expected:

stdIn:22.2-22.53 Error: expression doesn't match constraint [tycon mismatch]
  expression: (string * char list) list
  constraint: string parse_result
  in expression:
    ("a",#"a" :: nil) :: ("b",#"b" :: nil) :: nil: string parse_result

So I tried to define the datatype without type aliasing the parse_result as follows:

datatype 'a parse_result = ParseFailure
                         | ParseSuccess of ('a * char list) list;

Then suddenly it works:

([("a", [#"a"]), ("b", [#"b"])]);
val it = [("a",[#"a"]),("b",[#"b"])] : (string * char list) list
- ParseSuccess [("a", [#"a"]), ("b", [#"b"])];
val it = ParseSuccess [("a",[#"a"]),("b",[#"b"])] : string parse_result

I do not understand, why it will not accept my type alias string parse_result in place of (string * char list) list. Shouldn't that work? How else do I define 'a parse_result to be able to use it instead of ('a * char list) list?

My SMLNJ version is: Standard ML of New Jersey v110.79 [built: Sat Oct 26 12:27:04 2019]


Solution

  • The mistake was in the naming of the datatype. It has the same name as the type defined before it. Once it was renamed, the error went away. Working code is then:

    type 'a parse_data = ('a * char list);
    type 'a parse_result = 'a parse_data list;
    
    type 'a parser = char list -> 'a parse_result;
    
    datatype 'a result = ParseFailure
                       | ParseSuccess of 'a parse_result;