Search code examples
smlsmlnj

SML: Operator ```::``` is it true that is right assosiative and shoud be used as ```<value of type a>::<list with elements of type a>```?


Okay so I am a little confused about the cons operator : :: I know this is acceptable:

   > [2]
   or this
   2::[2,4]
   > [2,2,4]
and i know this is forbbiden
   [2]::[3]
it won't work.
but I recently found out that :
  [2]::[3]::nil
will work :
 > [[2],[3]]
or 
 [2]::[] will do as well.
 >[[2]]

My question is why? I was thinking , maybe it's a rule like if i have a list of type a then with operator cons I can only create a new list of type a. So for example when I have

[2] :: [3]
My lists have elements of type int but I am asking to concatenate into an int list a non init value [3] ??
But when I have [2]::[3]::[] , the empty list [] could be an empty list of any type so here I need it to be an empty list, with elements like [3], so it adds to the nil the element [3] and then the element [2] and so on ...
So is that the reason? Is there something else?


Solution

  • In SML, lists are defined as follows:

    datatype 'a list = nil | :: of 'a * 'a list
    

    In particular, :: is an infix constructor of type 'a * 'a list -> 'a list.

    The syntax [1, 2, 3] is sugar for 1 :: 2 :: 3 :: nil.

    You need not only construct lists containing ints (i.e., where 'a = int); for example, you could have list containing int lists, i.e. an int list list. That's what you created:

    [2] :: [3] :: nil
    (* can be sugared as *)
    [[2], [3]]
    

    (Similarly, you could pick 'a = string and create the list "hello" :: "world" :: nil, i.e. ["hello", "world"].)


    If you want to append two lists, you can use infix @, which has type 'a list * 'a list -> 'a list. For example:

    [1, 2] @ [3]
    (* evaluates to [1, 2, 3] *)