I'm trying to write a SML function that has two argument, the first is an
int and the second is a list of lists. The objective is to insert the first argument onto the front of every list in the second arguemnt. For example, append_to_front(1,[[3,4],[6,8],[]]) should return [[1,3,4],[1,6,8],[1]].
I have the code:
fun append_to_front(a:int, L:int list list) =
if L = []
then []
else a::hd(L)::append_to_front(a, tl(L));
and I get the error message: Error: operator and operand don't agree [tycon mismatch]. Why?
The cons operator :: has type 'a * 'a list -> 'a list, that is, it requires an element on the left and a list on the right. Moreover, it is right-associative, i.e., a::b::c = a::(b::c).
In your case, a has type int, b and c both have type int list. Consequently, the second use of :: isn't well-typed, because it has a list on both sides. Use list concatenation # in that place instead.
Related
I face a situation where a record is given a weak polymorphic type and I am not sure why.
Here is a minimized example
module type S = sig
type 'a t
val default : 'a t
end
module F (M : S) = struct
type 'a record = { x : 'a M.t; n : int }
let f = { x = M.default; n = (fun x -> x) 3 }
end
Here f is given the type '_weak1 record.
There are (at least) two ways to solve that problem.
The first one consists in using an auxiliary definition for the function application.
let n = (fun x -> x) 3
let f = { x = M.default; n }
The second one consists in declaring the type parameter of t as covariant.
module type S = sig
type +'a t
val default : 'a t
end
What I find strange is that the function application is used to initialize the field of type int that has no link at all with the type variable 'a of type t. And I also fail to see why declaring 'a as covariant suddenly allows to use arbitrary expressions in this unrelated field without losing polymorphism.
For your first point, the relaxed value restriction is triggered as soon as any computation happens in any sub-expression. Thus
neither
{ x = M.default; n = (fun x -> x) 3 }
nor
let n = Fun.id 3 in { x = M.default; n }
are considered a value and the value expression applies to both of them.
For your second point, this the relaxed value restriction at work: if a type variable only appears in strictly covariant positions, it can always be generalized. For instance, the type of
let none = Fun.id None
is 'a. 'a option and not '_weak1 option because the option type constructor is covariant in its first parameter.
The brief explanation for this relaxation of the value restriction is that a covariant type parameter corresponds to a positive immutable piece of data, for instance
type !+'a option = None | Some of 'a
or
type +'a t = A
Thus if we have a type variable that only appear in strictly covariant position, we know that it is not bound to any mutable data, and it can thus be safely generalized.
An important point to notice however, if that the only values of type 'a t for a t covariant in its first parameters are precisely those that does not contains any 'a. Thus, if I have a value of type 'a. 'a option, I know that I have in fact a None. We can in fact check that point with the help of the typechecker:
type forall_option = { x:'a. 'a option }
type void = |
let for_all_option_is_none {x} = match (x: void option) with
| None -> ()
| _ -> . (* this `.` means that this branch cannot happen *)
Here by constraining the type 'a. 'a option to void option, we have made the typechecker aware than x was in fact a None.
A function that decides if a list begins with the letter ’a’ can be defined as follows:
test :: [Char] -> Bool
test ['a',_] = True
test _ = False
or
test :: [Char] -> Bool
test ('a':_) = True
test _ = False
Why does the first use [], while the second uses ()?
Does the second use ('a':_) to represent a tuple or a list?
If a tuple, doesn't test's argument have a list type [Char]?
If a list, doesn't () represent a tuple and how can it represent a list?
Does the second use ('a':_) to represent a tuple or a list?
A list.
If a list, doesn't () represent a tuple and how can it represent a list?
No, this is the unit type [wiki]. It is not a tuple, nor a list. Sometimes, as the Wikipedia article says, it is interpreted as an 0-tuple. It is defined in GHC.Tuple as well.
Why does the first use [], while the second uses ()?
The two are not equivalent. The former one matches a list with exactly two elements where the first element is an 'a', whereas the latter matches a list with at least one element where the first element is an 'a'. But the latter can match a list with one element, three elements, etc. whereas the former can only match lists with exactly two elements.
Background
(:) is a data constructor of a list. Indeed:
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
The ('a': _) is just a nicer form of ((:) 'a' _). We here thus use one of the list data constructors.
The ['a', _] is syntactical sugar for (:) 'a' ((:) _ []), so here we match a list that starts with an 'a' and where the tail is a list with as head a value we do not care about and its tail the empty list data constructor.
Haskell's list notation is just syntactic sugar for "cons"ing elements on to the empty list (that is, using the : operator).
In other words,
[x,y,z]
is syntactic sugar for
x:(y:(z:[]))
(although this form would more normally be written as x:y:z:[] without the parentheses, since : is right-associative).
So, in the example you quote, ('a':_) represents any list whose first element is 'a', while ['a',_] is sugar for (a:(_:[])) which is a list of length exactly 2, whose first element is a.
Note that tuples are something else entirely, being denoted by a sequence of values in parentheses separated by commas.
In Haskell there are data constructors that are symbols, some examples that may confuse you:
() :: ()
that's the type unit with its constructor () and its value ()
then there is:
(,) :: a -> b -> (a,b)
(,) is the constructor for tuples, for example (1,"b") that can be (1,) “b” or (,) 1 “b”
finally your case:
(:) :: a -> [a] -> [a]
for example, 1:[] that can be [1] or (:) 1 []
OCaml arrays are mutable. For most mutable types, even an "empty" value does not have polymorphic type.
For example,
# ref None;;
- : '_a option ref = {contents = None}
# Hashtbl.create 0;;
- : ('_a, '_b) Hashtbl.t = <abstr>
However, an empty array does have a polymorphic type
# [||];;
- : 'a array = [||]
This seems like it should be impossible since arrays are mutable.
It happens to work out in this case because the length of an array can't change and thus there's no opportunity to break soundness.
Are arrays special-cased in the type system to allow this?
The answer is simple -- an empty array has the polymorphic type because it is a constant. Is it special-cased? Well, sort of, mostly because an array is a built-in type, that is not represented as an ADT, so yes, in the typecore.ml in the is_nonexpansive function, there is a case for the array
| Texp_array [] -> true
However, this is not a special case, it is just a matter of inferring which syntactic expressions form constants.
Note, in general, the relaxed value restriction allows generalization of expressions that are non-expansive (not just syntactic constants as in classical value restriction). Where non-expansive expression is either a expression in the normal form (i.e., a constant) or an expression whose computation wouldn't have any observable side effects. In our case, [||] is a perfect constant.
The OCaml value restriction is even more relaxed than that, as it allows the generalization of some expansive expressions, in case if type variables have positive variance. But this is a completely different story.
Also,ref None is not an empty value. A ref value by itself, is just a record with one mutable field, type 'a ref = {mutable contents : 'a} so it can never be empty. The fact that it contains an immutable value (or references the immutable value, if you like) doesn't make it either empty or polymorphic. The same as [|None|] that is also non-empty. It is a singleton. Besides, the latter has the weak polymorphic type.
I don't believe so. Similar situations arise with user-defined data types, and the behaviour is the same.
As an example, consider:
type 'a t = Empty | One of { mutable contents : 'a }
As with an array, an 'a t is mutable. However, the Empty constructor can be used in a polymorphic way just like an empty array:
# let n = Empty in n, n;;
- : 'a t * 'b t = (Empty, Empty)
# let o = One {contents = None};;
val o : '_weak1 option t = One {contents = None}
This works even when there is a value of type 'a present, so long as it is not in a nonvariant position:
type 'a t = NonMut of 'a | Mut of { mutable contents : 'a }
# let n = NonMut None in n, n;;
- : 'a option t * 'b option t = (NonMut None, NonMut None)
Note that the argument of 'a t is still nonvariant and you will lose polymorphism when hiding the constructor inside a function or module (roughly because variance will be inferred from arguments of the type constructor).
# (fun () -> Empty) ();;
- : '_weak1 t = Empty
Compare with the empty list:
# (fun () -> []) ();;
- : 'a list = []
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree;;
Is it a type definition, where a is a type parameter, and tree is the type name?
In Node of, is Node a built-in type of OCaml? What does of mean?
Thanks.
Yes 'a is a type parameter and tree is a type name (these are usually called variants in OCaml). This is reversed order from most other languages. Node is a constructor (called tag in OCaml) and of is just a keyword in OCaml to specify the types of the constructor arguments. Node is not a built-in type of OCaml (it is not even a type, but rather, as a I said, a constructor).
Hence Node (5, Empty, Node (6, Empty, Empty)) is something of type int tree (something like Tree<Int> in Java).
It may make more sense if you start with a simpler variant.
type shape = Square of int | Rectangle of int * int
Shape and Rectangle are tags (again constructors) that I have just made up that allow me to construct values of type shape (in this case I've chosen to have Shape take only one argument because only length is needed to specify a square, whereas Rectangles need both length and width). Nothing ever has a type of Shape or Rectangle, but things can have a type of shape.
One way to read that line in English is "I have defined a type called shape. A shape is either a Square of a single integer, or a Rectangle of two integers."
Now maybe for some reason I also want to label my shapes.
type 'label labelledshape = LabelledSquare of 'label * int | LabelledRectangle of 'label * int * int
The quote ' distinguishes that label is not a type (such as int), but is rather a variable. This allows me to write something like LabelledSquare ("a label for a square", 5) which is of type string labelledshape
Note that although this allows for polymorphism, these are not what is known as "polymorphic variants" in OCaml. I will not talk about that here, rather I'll just recommend either looking at OCaml documentation or browsing Stack Overflow for more details on that.
There are several kinds of type definitions:
Definition of a new sum type
From that type definition:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree;;
Here are roughly the "facts" that the OCaml compiler knows about based on it:
tree is a unary type constructor. That means that for any type t, t tree is a type as well (example: int tree).
Empty is a 0-ary constructor for 'a tree. That means that Empty has type t tree for any t.
Node is a 3-ary constructor. Here this means that if a has type t, b has type t tree, and c has type t tree, then Node (a, b, c)has typet tree(note: that's the samet`)
those are the only two ways to have a value of type t tree. That means that you can use pattern matching (match ... with | Empty -> ... | Node (a, b, c) -> ...).
Definition of a type alias
A definition can also be something that looks like:
type t = existing_type
In that case, t is just a new neame for the existing_type.
For example:
type 'a pp = Format.formatter -> 'a -> unit
This means that something that is a int pp has type Format.formatter -> int -> unit.
This is the type of a function that takes a formatter and an integer and returns unit. Such as :
type 'a pp = Format.formatter -> 'a -> unit
module M : sig
val pp_int : int pp
end = struct
let pp_int fmt n = Format.fprintf fmt "%d" n
end
I'm working on an assignment where I have to write a function to get the length of a list. This is a trivial task, but I've come across something that I don't understand.
My simple code
val len = foldr (fn(_, y) => y + 1) 0
produces this warning
Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
and when I try to run it in the REPL, I get this:
len [1, 2, 3, 4];
stdIn:18.1-18.17 Error: operator and operand don't agree [overload conflict]
operator domain: ?.X1 list operand:
[int ty] list in expression:
len (1 :: 2 :: 3 :: <exp> :: <exp>)
I don't understand why this doesn't work. I do know some functional programming principles, and this should work, since its very simple partial application.
Of course I can make it work without partial application, like this
fun len xs = foldr (fn(_, y) => y + 1) 0 xs
but I would like to understand why the first version doesn't work.
This is an instance of the value restriction rule application:
In short, the value restriction says that generalization can only occur if the right-hand side of an expression is syntactically a value.
Syntactically,
foldr (fn(_, y) => y + 1) 0
is not a value, it's a function application, that's why it hasn't been assigned a polymorphic type. It has been instantiated with a dummy type, which has a very limited use, e.g. this works:
len []
but in most cases len defined as val is useless.
This restriction exists to guarantee type safety in the presence of variable assignment (via references). More details can be found in the linked page.