Search code examples
smlsmlnj

SML: non-constructor applied to argument in pattern @


Why I can't do the following and what are the ways to do it?

datatype boolexp = zero
                 | one 
                 | compl of boolexp;

 fun convert (#"1"::nil) = one
   | convert (#"0"::nil) = zero
   | convert (#"-":: #"(" :: xs @ [#")"]) = compl (convert xs)

It gives me the errors:

non-constructor applied to argument in pattern: @
unbound variable or constructor: xs

Solution

  • The problem is in the last case of convert.

    @ is a function and not a value constructor (like :: and nil), so you cannot pattern-match on it. There is no way to pattern-match on the last element of a general list.

    To accomplish what you're trying to do, you can either:

    • Pattern-match the beginning out, i.e. #"-":: #"(":: xs, and then check if xs ends with a #")" using List.last.
    • If you need it to be faster than the approach above, you probably would need to use a specialized data structure that allows for faster reading from both ends of a list. This could for instance a double-ended queue. Okasaki has details on these.