Search code examples
sml

number_in_month exercise (Error: syntax error: replacing COLON with AS)


this is homework from the ProgLang course at Coursera but the due date has passed and I'm only auditing this. This is a really cheap problem but it looks like I can't do this in SML.

Given a list of date 3-tuples of int and an int, return how often that int matches #2 of the tuple (the month).

At first I had a lot of [tycon mismatch] and then played around with the function header. I have no idea how to denote a list of tuples, prolly all down to that.

fun number_in_month (date : [int*int*int], month : int) : int =
if hd date = []
then 0
else
if #2 hd date = month
then
    1 + number_in_month tl date
else
    0 + number_in_month tl date

Not sure about the logic and the if then else if construct either. And what on earth is AS ?

- use "hw1.sml";
[opening hw1.sml]
hw1.sml:13.26 Error: syntax error: replacing  COLON  with  AS
val it = () : unit

13:26 is the first colon of the header. Maybe I'm too numb to google too, I did not find anything useful.


Solution

  • In SML the list type is written as elementType list, not [elementType]. So the type of a list of int-triples is (int*int*int) list, not [int*int*int].

    So when SML sees the [, it thinks that it's seeing the start of a pattern (specifically a list pattern), not a type. That makes it think that the : is wrong (since a : must be followed by a type) and the error recovery algorithm replaces it with an as because that would be valid between an identifier and a pattern.

    And what on earth is AS ?

    It's a keyword used in pattern matches to assign a name to the result of a pattern match. For example if you want to match a three-element list with a list pattern, but you also want a name for the entire list you can write fun number_in_month (date as [x1, x2, x3]) = .... In this case, the three elements of the list would be known as x1, x2 and x3 respectively and the whole list would be known as date.

    Now there's no reason that you'd want to use the as keyword here. It just happens to be what the parser comes up with because fun number_in_month (date as [ can be the start of a syntactically valid program, but fun number_in_month (date : [ can not be.


    So your fixed signature should look like this:

    number_in_month (date : (int*int*int) list, month : int) : int =
    

    Now you'll get a bunch of type errors in the body of the function relating to some missing parentheses (for example#2 hd date is equivalent to the ill-typed (#2 hd) date, not #2 (hd date), which is what you want) and the fact that number_in_month takes two arguments, not one (in other words: you're missing the date argument when calling number_in_month recursively).