Why the compiler always wants this type once (=) is overloaded? - ocaml

I have a problem that I didn't understand since three days, since I don't understand, I can't solve it.
I have code like this:
module SpotLocation = struct
type t = {
uuid : string option;
netElement : string;
coordIntrinsic : float;
}
end
module Segment = struct
type t ={
netElement : string;
coordFrom : SpotLocation.t;
coordTo : SpotLocation.t;
}
let isEqual segA segB = segA.coordFrom = segB.coordFrom && segA.coordTo = segB.coordTo
let (=) = isEqual (* <<<<<<<<< Here is the problem *)
let isIn seg loc = (seg.netElement = loc.netElement)
end
The problem comes from (=) that I have overloaded.
Once I have it, the compiler insists have the following reaction:
Error: This expression has type string but an expression was expected of type t
I have tried to declare the signature of (=) but it doesn't work.
For example, this gives the same thing:
module Segment = struct
type t ={
netElement : string;
coordFrom : SpotLocation.t;
coordTo : SpotLocation.t;
}
let isEqual segA segB = segA.coordFrom = segB.coordFrom && segA.coordTo = segB.coordTo
let ((=) : t -> t -> bool) = isEqual (* <<<<<<<<< Here is the problem *)
let isIn (seg : t) (loc : SpotLocation.t) =
let open SpotLocation in
seg.netElement = loc.netElement
end
If I move the (=) after isIn, it works, but once I start to add some more logic it gives the same error. So I don't know what happens.
Could anyone explain this to me? Thank you!

There is no function overloading in OCaml. Once you define a function (or any other type of value for that matter) with a given name, that name will shadow any existing value with the same name for as long as it is in scope.
So once you define your global = function, the old = is no longer accessible for the rest of the file, except via its fully qualified name Pervasives.=.

Related

How to Define Something that Acts as a Dictionary of Unique Functions in F#?

It is my understanding that a Dictionary's elements must all be the same (ie: unit -> unit)
I need a way to add functions to an object, similar to a Dictionary, but my problem is that the functions have different Types. The only thing I can know for sure is that added functions will always follow a pattern of int -> 'T where 'T could be any Type. All functions in the object could be made to inherit from a shared type if needed. Here is a non-functioning example of how it would be used.
let myFunctions = Dictionary<int,int -> unit>()
let exampleFunction0 (x : int) : int = x + 1
let exampleFunction1 (x : int) : byte = (byte)x
let exampleFunction2 (x : int) : string[] = Array.create<string> 1 "test"
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x = myFunctions.Item(randomNumber) x
It is important to note that which one of the functions that gets called is random and I cannot know it. The purpose of the dictionary is to hold the functions that will be called randomly. As in the examples, the results are not the same as I need the results to be different for each function. x will always be the same, but the result of the function will not.
The code will be in a library to be reused, so functions may be added that I will never see.
You need to unify the output types to make this work.
If all the types are known you should use a Discriminated Union.
type ReturnValues =
| Case0 of int
| Case1 of byte
| Case2 of string[]
let myFunctions = Dictionary<int,int -> ReturnValues>()
let exampleFunction0 (x : int) = x + 1 |> Case0
let exampleFunction1 (x : int) = (byte)x |> Case1
let exampleFunction2 (x : int) = Array.create<string> 1 "test" |> Case2
myFunctions.Add(0, exampleFunction0)
myFunctions.Add(1, exampleFunction1)
myFunctions.Add(2, exampleFunction2)
let randomNumber = System.Random().Next(3)
let result x : ReturnValues = myFunctions.Item(randomNumber) x
If you don't know all the types you can make all the return types obj (Dictionary<int,int -> obj>) using the box function or you can make all the return types implement a common interface.
What has ultimately solved the problem for me is to package together the Type and Object. This package is what the functions that will be added to the dictionary must return. This way there is a standard way for new types to be added after compilation.
open System.Collections.Generic
open System
// a package that can hold an object and its type
type package(x, y) =
member this.x : Type = x
member this.y : Object = y
//empty class for testing
type testClass() = class end
//custom types for testing
type fiy(x) =
member this.Value : string = x
type foe(x) =
member this.Value : testClass = x
//functions for testing
let func0 (x: int) : package = package(typeof<int>, x)
let func1 (x: int) : package = package(typeof<fiy>, fiy("potato"))
let func2 (x: int) : package = package(typeof<foe>, foe(testClass()))
let myFunctions = Dictionary<int, (int -> package)>()
//example use of adding a function
myFunctions.Add(0, (func0))
myFunctions.Add(1, (func1))
myFunctions.Add(2, (func2))
//pick a random number to test with; as we will have no idea which function will be ran
let randomNumber = System.Random().Next(3)
let pickedFunction x : package = (myFunctions.Item(randomNumber) x)
let ranFunction = pickedFunction 5 //just some filler number to test with
printfn "The type of the ranFunction is: %s" (ranFunction.x.ToString())

Use abstract module as part of type definition separate from module

I'm trying to use the module type Partial_information which is constructed via the functor Make_partial_information as the type of the field contents in the type Cell.t. However, I'm getting the error Unbound module Partial_information.
open Core
(* module which is used as argument to functor *)
module type Partial_type = sig
type t
val merge : old:t -> new_:t -> t
end
(* type of result from functor *)
module type Partial_information = sig
type a
type t = a option
val merge : old:t -> new_:t -> t
val is_nothing : t -> bool
end
(* The functor *)
module Make_partial_information(Wrapping : Partial_type):
(Partial_information with type a = Wrapping.t)
= struct
type a = Wrapping.t
type t = a option
let merge ~(old : t) ~(new_ : t) =
match (old, new_) with
| (None, None) -> None
| (None, Some a) -> Some a
| (Some a, None) -> Some a
| (Some a, Some b) -> (Wrapping.merge ~old:a ~new_:b) |> Some
let is_nothing (it: t) : bool = (is_none it)
end
(* Checking to make sure understanding of functor is correct *)
module Int_partial_type = struct
type t = int
let merge ~old ~new_ = new_ [##warning "-27"]
end
module Int_partial_information = Make_partial_information(Int_partial_type)
(* Trying to use _any_ type which might have been created by the functor as a field in the record *)
module Cell = struct
type id = { name : string ; modifier : int }
type t = {
(* Error is here stating `Unbound module Partial_information` *)
contents : Partial_information.t ;
id : id
}
end
Module types are specifications for modules. They do not define types by themselves. They are also not constructed by functors in any way.
Consequently, it is hard to tell what you are trying to do.
As far I can see, you can simply define your cell type with a functor:
module Cell(P : Partial_information) = struct
type id = { name : string ; modifier : int }
type partial
type t = {
contents : P.t;
id : id
}
end
Or it might be even simpler to make the cell type polymorphic:
type 'a cell = {
contents : 'a;
id : id
}
since the type in itself is not particularly interesting nor really dependent upon
the type of contents.
P.S:
It is possible to use first class modules and GADTs to existentially quantify over a specific implementation of a module type. But it is unclear if it is worthwhile to explode your complexity budget here:
type 'a partial_information = (module Partial_information with type a = 'a)
module Cell = struct
type id = { name : string ; modifier : int }
type t = E: {
contents : 'a ;
partial_information_implementation: 'a partial_information;
id : id
} -> t
end

OCaml - confusion from type alias (warning 40)

I don't understand why OCaml is not able to figure out that there is no room for confusion here: anint below can't be other one but A's.
module A = struct
type test = Graphics.status
end
module type ASIG = sig
type test = A.test
val atest : test
end
module Func (H : ASIG) = struct
let _ = let open H in atest.key
end
However, it raises
Warning 40: key was selected from type Graphics.status.
It is not visible in the current scope, and will not
be selected if the type becomes unknown.
How can I tell it "it's fine" without disabling the warning?
I'm aware I can solve it by opening A. However, if H defines its own functions and types similar---but not equal---to A, then it will have unnecessary clashes. I also know I can duplicate the definition, but that defeats the purpose of type aliasing, and involves lots of unnecessary code duplication. Perhaps there is no solution, but I wonder why OCaml is so blind dumb on this one: type alias should mean also constructor and record fields alias, shouldn't it?
You can simply open the the module defining the original type locally when referring to the field key as in the following:
module A = struct
type test = Graphics.status
end
module type ASIG = sig
type test = A.test
val atest : test
end
module Func (H : ASIG) = struct
let _ = let open H in atest.Graphics.key
end
Or if you need to refer to several fields :
let _ = let open H in Graphics.(atest.key, atest.button)
Well, this happens because the module signature ASIG needs to look the definition of type test for the implementation of A. This often causes problems with visibility of the types, and sometimes require duplication of type definitions, where the contract satisfies the implementation instead of referring to it.
How can we fix this warning? In ASIG, instead of defining type test = A.test, we need to explicitly do type test = { anint: int }as we did in the implementation, so:
module ASIG = sig
type test = { anint: int }
val atest : test
end
module A = struct
type test = { anint: int }
end
module Func (H : ASIG) = struct
let _ = let open H in atest.anint
end
The H module would not be able to view anintin its scope, otherwise, because the signature has a type (contract) that links to the implementation. It is also a core concept of OCaml philosophy isolating signatures and implementations and avoiding signatures depending upon implementations.

type mismatch error declaring list of classes

def getValueAndItsType() : List[ (AnyRef, Class[_]) ] = {
val dataSet1 = ("some string data", classOf[String])
val dataSet2 = (new Thread(), classOf[Thread])
val dataSet3 = (new NullPointerException(), classOf[NullPointerException])
val dataSet4 = (5, classOf[Int])
val list = List(dataSet1, dataSet2, dataSet3, dataSet4)
list
}
Type type mismatch; found :
List[(Any, Class[_ >: Int with NullPointerException with Thread with
String])] required: List[(AnyRef, Class[_])]
If dataSet4 is removed from List, the compile time error disappears
Please suggest, what is wrong with Class[_]. Isn't it
equivalent to Class[?] in java ? I appreciate, if you also suggest
correct declaration for doing this..
In Scala:
Any is the root of the Scala class.
AnyRef is the root of the class of reference types, it extends from Any.
AnyVal is the root class of all value types. it extends from Any
Null is a subtype of all reference types.
Nothingis a subtype of all other types including Null
So base on your code, you need to extend from Any, include AnyRef: reference types and AnyVal: values types.
def getValueAndItsType() : List[ (Any, _ <: Any) ] = {
val dataSet1 = ("some string data", classOf[String])
val dataSet2 = (new Thread(), classOf[Thread])
val dataSet3 = (new NullPointerException(), classOf[NullPointerException])
val list = List(dataSet1, dataSet2, dataSet3)
list
}

Mutually recursive module and functor in OCaml

I have defined an interface A to be used by several functors, and notably by MyFunctor :
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
Now I want to define a module B with implements the interface A. In particular, the implementation of complex_func should use basic_func through complex_impl in MyFunctor :
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
However, this code doesn't compile as B is not fully declared in the context of MyFunctor(B). Obviously B depends on MyFunctor(B), which itself depends on B, so I tried to use the rec keyword on module B, but it didn't work out.
So, is it possible to do something like this ? It would be useful as I have several modules B_1, ..., B_n that use the same implementation of B_k.complex_func in terms of B_k.basic_func.
Or is there a better pattern for my problem ? I know that I can declare complex_impl as a regular function taking basic_func as a parameter, without using a functor at all :
let complex_impl basic_func params =
...
basic_func ...
...
But in my case complex_impl uses many basic functions of A, and I think that the paradigm of functors is clearer and less error-prone.
Edit : I followed this answer, but in fact, A uses some type t that is specialized in B :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
And now I get the error (for x at line Impl.complex_impl x) :
This expression has type t = int but an expression was expected of type B.t
Edit 2 : I solved this second problem with the following code :
module rec B :
A with type t = int
= struct
type t = int
...
end
You can use recursive modules just like you'd write recursive let bindings
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
Note (a) the module rec bit in the definition of B and (b) that I am required to provide a module signature for a recursive module definition.
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
There's a small caveat, however, in that this only works because the signature A has only values which are function types. It is thus known as a "safe module". If basic_func and complex_func were values instead of function types then it would fail upon compilation
Error: Cannot safely evaluate the definition
of the recursively-defined module B