How to implement a module signature in OCaml with some default implementation? - ocaml

I want to implement a module signature in OCaml like below, where the function get_data depends on each module implementation and return an option type. I also want to provide the function get_data_exn which is a wrapping of get_data by un-optioning the result of get_data, and throwing an exception when the result returned by get_data is None
module type Foo = sig
type t
val get_data : int -> t option
val get_data_exn : int -> t
end
In essence, the implementation of the function get_data_exn will be like below, and it will be the same for all modules that implement Foo:
let get_data_exn value = match get_data value with
| Some data -> data
| None -> raise DataNotFound
Is this possible for me to include this implementation of get_data_exn inside the signature Foo so that I don't have to repeat it for other modules? This is something similar to abstract class in Java.
Thank you for spending time to consider my question.

You can define a core module type
module type Foo_core = sig
type t
val get_data: int -> t option
end
and extend it with a functor:
module Get_data_exn(Core:Foo_core) = struct
let get_data_exn value = match Core.get_data value with
| Some data -> data
| None -> raise DataNotFound
end
Depending on your use case, it might be useful to expose a standard Make_foo functor
module Make_full_Foo(X:Foo_core) = struct
include X
include Get_data_exn(X)
end

Related

How to apply [##deriving show] to a type from module parameter of my functor?

I have a functor that takes a Set type like:
module type MySet = functor (S : Set.S) -> sig
val my_method : S.t -> S.elt -> S.elt list option
end
module MySet_Make : MySet = functor (S : Set.S) -> struct
let my_method set el = Some [el] (* whatever *)
end
module IntSet = Set.Make(Int)
module MyIntSet = MySet_Make(IntSet)
S.elt is the type of elements of the set
I want to apply [##deriving show] (from https://github.com/ocaml-ppx/ppx_deriving#plugin-show) to S.elt within my functor somehow, so that in one of my methods I can rely on having a show : S.elt -> string function available.
I feel like it must be possible but I can't work out the right syntax.
Alternatively - if there's a way to specify in the signature that the Set type S was made having elements of a "showable" type.
e.g. I can define:
module type Showable = sig
type t [##deriving show]
end
...but I can't work out how to specify that as a type constraint to elements of (S : Set.S)
You can construct new signatures that specify the exact function show you need:
module MySet_Make(S : sig
include Set.S
val show : elt -> string
end) = struct
let my_method _set el =
print_endline (S.show el);
Some [el]
end
Then you can build the actual module instance by constructing the module with the needed function:
module IntSet = struct
include Set.Make(Int)
(* For other types, this function could be created by just using [##deriving show] *)
let show = string_of_int
end
module MyIntSet = MySet_Make(IntSet)
Ok, after a couple of hours more fumbling around in the dark I found a recipe that does everything I wanted...
First we define a "showable" type, representing a module type that has had [##deriving show] (from https://github.com/ocaml-ppx/ppx_deriving#plugin-show) applied to it:
module type Showable = sig
type t
val pp : Format.formatter -> t -> unit
val show : t -> string
end
(I don't know if there's some way to get this directly from ppx_deriving.show without defining it manually?)
Then we re-define and extend the Set and Set.OrderedType (i.e. element) types to require that the elements are "showable":
module type OrderedShowable = sig
include Set.OrderedType
include Showable with type t := t
end
module ShowableSet = struct
include Set
module type S = sig
include Set.S
end
module Make (Ord : OrderedShowable) = struct
include Set.Make(Ord)
end
end
I think with the original code in my question I had got confused and used some kind of higher-order functor syntax (?) ...I don't know how it seemed to work at all, but at some point I realised my MySet_Make was returning a functor rather than a module. So we'll fix that now and just use a normal functor.
The other thing we can fix is to make MySet a further extension of ShowableSet ... so MySet_Make will take the element type as a parameter instead of another Set type. This makes the eventual code all simpler too:
module type MySet = sig
include ShowableSet.S
val my_method : t -> elt -> elt list option
val show_el : elt -> string
end
module AdjacencySet_Make (El : OrderedShowable) : AdjacencySet
with type elt = El.t
= struct
include ShowableSet.Make(El)
let my_method set el = Some [el] (* whatever *)
let show_el el = El.show el (* we can use the "showable" elements! *)
end
Then we just need an OrderedShowable version of Int as the element type. Int is already ordered so we just have to extend it by deriving "show" and then we can make a concrete MySet:
module Int' = struct
include Int
type t = int [##deriving show]
end
module MyIntSet = MySet_Make(Int')
And we can use it like:
# let myset = MyIntSet.of_list [3; 2; 8];;
# print_endline (MyIntSet.show_el 3);;
"3"

How to use a functor in OCaml

I can't find on the internet how to use the functor I've written. I will post a minimal code, if you need more contextual information tell me and I'll add, but I'm sure it's really easy to do.
I think I just don't understand what a functor is, I see things like this (I will use an analogy with Java to ilustrate my understanding since I'm new to OCaml) :
sig (=) Interface MyInterface
struct (=) Object implements MyInterface
functor (=) MyInterfaceBis extends MyInterface
The following example I'm about to give is stupid, it's just so I can understand the concept behind it :
module type tF = sig
type 'a t
val create : 'a t
end
module F : tF = struct
type 'a t = 'a list
let create = []
end
module type tF2 = functor(F : tF) -> sig
val foo : 'a F.t -> 'a F.t
end
module F2 : tF2 = functor(F : tF) -> struct
let foo f = f
end
I know I can do for example :
let test = F.create
But I don't know how to use F2.
I've tried this page but it's not using my notation and I was more confused after than before.
F2 takes in a module with type tF and produces a module with one function foo:
module NewF = F2 (F)
For more information, see the section about functors in Real World OCaml.

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.

Testing interfaces with foq

I am trying to use Foq to testing an interface with Foq.
So far, all examples I have seen for this have been relatively simple, such as the following:
let users = [|{ID = 1; pass = true};{ID = 2; pass= false}|]
type IFoo =
abstract member Bar: int -> bool
//tests with Foq
let dataAccess =
Mock<IFoo>()
.Setup(fun x-> <# x.Bar(users.[0].ID) #>).Returns(users.[0].pass)
.Setup(fun x-> <# x.Bar(users.[1].ID) #>).Returns(users.[1].pass)
.Create()
The examples have been sourced from 'Testing with F# - Mikael Lundin'
I have also researched this through a bit of googling (this link was helpful - http://trelford.com/blog/post/Foq.aspx)
However, the real Interfaces I want to test are the following:
type IParameters =
abstract member ParameterDate : int->string->DateTime
type IDataSource =
abstract member MortParameters: IParameters
I have tried a number of different ways to test these (e.g. defining a function with a signature of int->string to be used as the input to the setup. Alternatively, having the return value as a string->DateTime and the Setup as just an integer.
My question is really the following: When testing interfaces using Foq, how can I extend the testing to interfaces with function signatures of any general length (e.g. a->b->c->d->e etc.)
Since ParameterDate a property with a function type, you could just set it up as a property that returns a lambda value. See an example of property set-up in Foq. This should be easy to modify for your case:
let instance =
Mock<System.Collections.IList>()
.Setup(fun x -> <# x.Count #>).Returns(1)
.Create()
However, I guess you would lose the ability to have a strict mock with fixed expectations on the function inputs.
To enforce only expected inputs for the function returned by the mock property you could provide a function like this:
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Invalid mock input"
I would probably stop here, but if you're working with code where you need to verify a function was called, as opposed to just ensuring you get the correct output, you could add a helper like this:
type Verifiable<'a, 'b> (f : 'a -> 'b) =
let called = ref false
member this.Func x =
called := true
f x
member this.Verify() =
if not called.Value then failwith "Mock function was not called"
And here's how you would use it:
let parameterDateMock =
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Unexpected mock input"
|> Verifiable
let parameters =
{ new IParameters with member this.ParameterDate i s = parameterDateMock.Func i s }
parameters.ParameterDate 1 ""
parameterDateMock.Verify()
Caveat: This only verifies the function was called with at least one parameter. It may have returned another function by currying and not actually run the code in the mock function body. To get around that you'd need a variation of the Verifiable class for every function arity and use the right one in each case.

How to merge OCaml module types (signatures) defining the same type?

In OCaml, I have two module types defining a type t:
module type Asig = sig
type t
val a : t
end
module type Bsig = sig
type t
val b : t
end
I want to automate the creation of a module type merging them. I want to create a module type equivalent to:
module type ABsig_manual = sig
type t
val a : t
val b : t
end
I tried
module type ABsig = sig
include Asig
include Bsig
end
but this fails with Error: Multiple definition of the type name t. It seems impossible to add a type constraint to the include so I'm stuck.
Context: I have a module AB that does implement both signatures and I want to feed it to a functor like:
module MakeC(AB) = struct
type t = AB.t list
let c = [AB.a; AB.b]
end
module C = MakeC(AB)
I could use two arguments like in:
module UglyMakeC(A : Asig)(B : Bsig with type t = A.t) = struct
type t = A.t list
let c = [A.a; B.b]
end
module C = UglyMakeC(AB)(AB)
but this (is ugly and) doesn't scale well to more functors or more signatures to merge.
So, how can I automate merging those two module types? I can modify A and B as needed but I want to keep them separated. Also, maybe my approach is completely wrong, and in that case I'd love pointers to a better direction.
Type sharing in OCaml - typechecker error is related but merges modules, not module types.
Here is the way to do it :
module type Asig = sig
type t
val a : t
end
module type Bsig = sig
type t
val b : t
end
module type ABsig = sig
include Asig
include Bsig with type t := t
end
It's called "destructive substitution".