OCaml Stack of tuples - stack

I am trying to create a stack of tuples in OCaml using the following piece of code
let (k : (string*string) Stack.t) = Stack.create ;;
But when doing so i get an error while compiling telling
Error: This expression has type unit -> 'a Stack.t
but an expression was expected of type (string * string) Stack.t
Am pretty new to OCaml. Can someone point out where I am going wrong?

Stack.create is a function which takes the value () (of type unit) and give you back a stack.
So you should do:
let (k : (string*string) Stack.t) = Stack.create ();;
if you write Stack.create, you just speak about the function, not the result.

Related

Ocaml Stack push creates a type error

So in when I try to push to a stack
# let s = Stack.create ;;
val s : unit -> 'a Stack.t = <fun>
# Stack.push 1 s ;;
in utop or ocaml toplevel i get an error
Error: This expression has type unit -> 'a Stack.t
but an expression was expected of type int Stack.t
Why? How should should I do it? There are examples that say this should work.
Stack.create is a function that takes a unit argument. You are using it as a value, assigining the create function to s, hence the toplevel printing the type as val s : unit -> 'a Stack.t = <fun>.
The correct way to create a stack is with let s = Stack.create ();;

type inference on abstract type with a tuple

Based on this kvb's answer, this code compiles (F#4) and runs :
type Untupler = abstract Apply : 'u * 'u -> 'u
let myotherFun arg1 arg2 =
printfn "myotherFun result is : %A %A" arg1 arg2
let myFunction tup1 tup2 (i:Untupler) =
myotherFun (i.Apply tup1) (i.Apply tup2)
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply (x,y) = snd (x,y) }
But if the last line is replaced by the initial answer :
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply x = fst x }
then the compiler complains with error FS0768 :
The member 'Apply' does not accept the correct number of arguments, 2 arguments are expected
I do not understand why the compiler seems to fail to infer that x is indeed a tuple. Or is there another issue I am missing ? Thx.
The reason for this is that when you start using interfaces, you move into F#'s support for Object-Oriented Programming, and in F#, all OOP interop methods are tupled by default.
Thus, the Apply method is interpreted as being a method that takes two method arguments, rather than a function that takes a single tuple as input.

Variance of function types wrt. interfaces

I'm trying to understand the variance rules for function types. It seems they don't treat input and output the same (up to duality). Consider this program.
let mk1 s = s |> Seq.iter (fun _ -> ())
// val mk1 : s:seq<'a> -> unit
let mk2 = mk1 : list<int> -> unit // Ok.
let mk3 () = [1]
// val mk3 : unit -> int list
let mk4 = mk3 : unit -> seq<int> // Type mismatch.
This is the error:
Type mismatch. Expecting a
unit -> seq<int>
but given a
unit -> int list
The type 'seq<int>' does not match the type 'int list'
It's my understanding that seq<int> is an interface type, one which int list implements, so I was expecting this cast to go through(*).
Two questions:
Why doesn't it?
Why is the cast producing mk2 ok?
(*) For theorists: I was expecting the elaborator to exhibit dual behaviour on the input and output positions of the function space type constructor. Is that wrong?
You have this:
let mk4 = mk3 : unit -> seq<int>
Which will not compile, the up-cast will happen automatically in the input parameter but never in the output of the function. This is in the spec, section 14.4.2 Implicit Insertion of Flexibility for Uses of Functions and Members.
This means that F# functions whose inferred type includes an unsealed type in argument position may be passed subtypes when called, without the need for explicit upcasts.
This makes possible to define another version of the function which is restricted to a subtype, which are the other cases you're showing.
Interestingly, you can use flexible types to define mk4 as follows:
let mk4 = mk3 : unit -> #seq<int>
It compiles but automatically lifts the type of mk4 up to unit -> int list

Value restriction when there are no generic parameters

I get the value restriction error on let makeElem in the following code:
let elemCreator (doc: XmlDocument) =
fun name (value: obj) ->
let elem = doc.CreateElement(name)
match value with
| :? seq<#XmlNode> as childs ->
childs |> Seq.iter (fun c -> elem.AppendChild(c) |> ignore)
elem
| _ -> elem.Value <- value.ToString(); elem
let doc = new XmlDocument()
let makeElem = elemCreator doc
Why I get the value restriction error if anonymous function returned from elemCreator hasn't any generic parameters?
The compiler states that the infered type of makeElem is (string -> 'a -> XmlNode). But why it infers second parameter as 'a if I've declared it as obj?
I believe that this may be the "expected" behavior (although unfortunate in this case), as a result of the compiler's generalization and condensation processes. Consider Tomas's example:
let foo (s:string) (a:obj) = a
If you were to define
let bar a = foo "test" a
then the compiler will infer the type bar : 'a -> obj because it generalizes the type of the first argument. In your case, you have the equivalent of
let bar = foo "test"
so bar is a value rather than a syntactic function. The compiler does essentially the same inference procedure, except now the value restriction applies. This is unfortunate in your case, since it means that you have to explicitly annotate makeElem with a type annotation (or make it a syntactic function).
This looks like an unexpected behavior to me. It can be demonstrated using a simpler function:
let foo (s:string) (a:obj) = a
let bar = foo "bar" // Value restriction
One possible explanation might be that the F# compiler allows you to call a function taking parameter of some type with an argument of any subtype. So, you can call foo "hi" (new A()) without explicitly casting A to obj (which used to be required some time ago).
This implicit casting could mean that the compiler actually interprets bar as something like this:
let bar a = foo "bar" (a :> obj)
...and so it thinks that the argument is generic. Anyway, this is just a speculation, so you could try sending this as a bug report to fsbugs at microsoft dot com.
(The following is based solely on observation.)
If you have a function obj -> 'a, calls to that function are not used to infer/solve the type of its argument. An illustration:
let writeLine (arg: obj) = System.Console.WriteLine(arg)
writeLine is obj -> unit
let square x =
writeLine x
x * x
In the above function x is inferred as int because of (*). If a type could be constrained by obj then this function would not work (x would be inferred as obj prior to the use of (*), which would cause an error along the lines of: type obj does not support operator (*)).
I think this behavior is a Good Thing. There's no need to restrict a type as obj because every type is already implicitly convertible to obj. This allows your program to be more generic and provides better interoperability with the .NET BCL.
In short, obj has no bearing on type inference (yay!).

Can't get operator overloading to work with Linq Expression Trees

I am creating Linq expression trees from F# that operates on a custom datatype I have. The type is a very simple discriminated union that has the usual arithmetic operators overloaded. But for some reason I cannot create arithmetic linq expression nodes due to the fact that it can't find the correct overload. Thing is, I swear I had this working some time ago but I can't figure out what I changed to make it break.
I'll attach a small code sample showing the problem. The datatype below has the Addition operator overloaded. Using the overloaded operator works like a charm, but when I try to create an addition expression tree node using Expression.Add(lhs, rhs) the system throws an exception complaining that it can't find the overload for the Add operation.
Does anyone have an idea of what I am doing wrong?
Thank you,
Rickard
open System.Linq.Expressions
module DataType =
exception NotImplementedYet of string
type DataCarrier =
| ScalarCarrier of float
| VectorCarrier of float array
member this.Add(other) =
match (this, other) with
| ScalarCarrier(x), ScalarCarrier(y) -> ScalarCarrier(x + y)
| VectorCarrier(u), VectorCarrier(v) ->
VectorCarrier(Array.map2 (fun x y -> x + y) u v)
| _,_ -> raise (NotImplementedYet("No go!"))
static member (+) (lhs:DataCarrier, rhs) =
lhs.Add(rhs)
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs)
(* no problems with this one *)
printf "Testing operator overloading: %A" (DataType.ScalarCarrier(1.0)
+ DataType.ScalarCarrier(2.0))
(* this throws an exception *)
printf "Testing expr construction %A" (Main.createAddOp
(DataType.ScalarCarrier(1.0))
(DataType.ScalarCarrier(2.0)))
One solution is to explicitly type the Expression operands (giving them the static type DataType.DataCarrier instead of their runtime type DataType.DataCarrier.ScalarCarrier):
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs, typeof<DataType.DataCarrier>)
let crhs = Expression.Constant(rhs, typeof<DataType.DataCarrier>)
Expression.Add(clhs, crhs)
Another option would be to explicitly pass the addition operator to use:
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs, typeof<DataType.DataCarrier>.GetMethod("op_Addition"))
I am surprised that your original code doesn't work, though. It appears to be a limitation in how expression trees find relevant add operators (that is, it appears that Linq only looks for add operators on the runtime types of operands).

Resources