F# lets you turn operators into functions by surrounding them with (
)
: for instance, (+)
is of type int -> int -> int
.
Is it possible to do this with the list cons operator, ::
?
It doesn't behave like a normal binary operator:
FSI> (::);;
(::);;
-^^
c:\temp\stdin(3,2): error FS0010: Unexpected symbol '::' in expression.
Expected ')' or other token.
And the List.Cons
method takes a tuple; it's not curried.
(It's useful to be able to do this. For instance, you can use it to implement map in terms of fold).
Paraphrased from http://cs.hubfs.net/forums/permalink/11713/11713/ShowThread.aspx#11713
(::)
is a discriminated union 'constructor' for the list<'a> type
, and so raised the question of whether as a function value its arguments should be curried (like +
) or tupled (like all DU constructors). Either way seems fishy/unexpected to some people, so F# simply disallows the construct.
Of course you can always write e.g.
let cons x y = x :: y
and use cons
, or just use a lambda fun x y -> x::y
, if you want a "curried prefix function of two args" for this.
Unfortunately, no, you can't. ::
is not an operator, but a "symbolic keyword" according to the language grammar (see section 3.6 of the spec), as are :?>
and a few others. The language doesn't seem completely consistent here, though, since there are a few symbolic keywords which can be treated as though they were operators (at least (*)
and (<@ @>)
).
::
and []
can both be represented by List<_>.Cons
and List<_>.Empty
respectively. Keep in mind though that the former takes a tuple as an argument. These are here so lists can be created in languages other than F#.
> List.Cons(4, List.Empty);;
val it : int list = [4]
> 4::[];;
val it : int list = [4]
> List<int>.Cons(4, List<int>.Empty);;
val it : int list = [4]
> List.Cons;;
val it : 'a * 'a list -> 'a list = <fun:clo@24-7> //'
> List<int>.Empty;;
val it : int list = []