caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] On variants, integers and testing
@ 2018-03-16 11:12 Bahman Movaqar
  2018-03-19 10:41 ` Cedric Cellier
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Bahman Movaqar @ 2018-03-16 11:12 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1977 bytes --]

I'm new to OCaml so please bear with me.

As a practice, I implemented the solution to problem 54 of Project Euler
(poker hands).

* The original problem https://projecteuler.net/problem=54
* The solution:
  - https://github.com/bahmanm/euler-ml/blob/master/src/p54.mli
  - https://github.com/bahmanm/euler-ml/blob/master/src/p54.ml
  - https://github.com/bahmanm/euler-ml/blob/master/test/test_p54.ml

I have 2 questions and 1 favour to ask :-)

Q1
==
To limit the values possible for a card's actual value, I defined `Value`
module (line 6) which basically maps a variant to integer values.
Is this the idiomatic approach? Is there something like Java's enum or
Pascal's subranges that I could use[1]?

Q2
==
Suppose that I wrote this piece of code as a library to be used by others
as well. In such a case, practically the only function that the users are
interested in is `solve`, as defined in the .mli file.
This is good: keeps my library clean, the usage straight-forward and
doesn't confuse the users.

However, when it comes to testing, things are not that simple. Now that I
have exported only 1 function in the .mli, I can only test that 1 function.
Is this the proper way[2]?

Favour
======
I'd be really grateful if somebody would spend some of her/his precious
time and took a look at the code that I wrote, just to give me broad
pointers how this can be improved or be more idiomatic.

[1] I noticed Batteries bounded types, but when I used it, it felt like an
overkill for my purpose.
[2] I know this is a rather general question and the same question can be
applied to any other language. However some languages, such as D, let you
write unit tests next to the main code - or many OO languages have the
visibility modifier which can help.

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 4725 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-16 11:12 [Caml-list] On variants, integers and testing Bahman Movaqar
@ 2018-03-19 10:41 ` Cedric Cellier
  2018-03-19 10:44   ` Cedric Cellier
  2018-03-19 13:27 ` Yawar Amin
  2018-03-19 21:24 ` SP
  2 siblings, 1 reply; 7+ messages in thread
From: Cedric Cellier @ 2018-03-19 10:41 UTC (permalink / raw)
  To: Bahman Movaqar; +Cc: caml-list

-[ Fri, Mar 16, 2018 at 12:12:56PM +0100, Bahman Movaqar ]----
> However, when it comes to testing, things are not that simple. Now that I
> have exported only 1 function in the .mli, I can only test that 1 function.
> Is this the proper way[2]?

This is one of the reasons some people don't like to use mli files.

Another approach is to define (and document) the signatures in ".ml" file
(named for instance "yadayada_intf.ml") and then the implementation can be
written and exposed fully, knowing that you can create another one and
constraint it to the signature later on. Example:

--- yadayada_intf.ml --- 8< --- 8< ---
(** This is library yadayada *)

module type S =
sig
  (** The type of yadayadas *)
  type t

  (** Create a yadayada from a xyz: *)
  val create : xyz -> t

  (** Call this to perform a foo with your yadayada created with [create]: *)
  val foo : t -> wooz
end
--- >8 --- >8 ---

Then you implement the actual thing in yadayada_impl.ml:

--- yadayada_impl.ml --- 8< --- 8< ---
(* Implementation for yadayada *)

type t = ...
let create x = ...
let foo t = ...
--- >8 --- >8 ---

That implementation you can test from "yadayada_tests.ml" for instance, since
none of it is hidden.

Then, you can provide users with a simplified module Yadayada.M, defined in
"yadayada.ml":

--- yadayada.ml --- 8< --- 8< ---
module M = Yadayada_impl : Yadayada_intf.S
--- >8 --- >8 ---

Plenty of variations are possible of course, but the names "t" for the main
type, "S" for the main signature and "M" for the main module (or "Make" if it's
a functor) are common.

The drawback of this technique is that it tends to lead toward a design with
plenty of modules and functors, which makes reading the code more complex (and
is also harder to inline efficiently).

Note that for inline tests you have the qtest
(https://github.com/vincent-hugot/qtest) tool that I find quite nice for inline
tests as long as you do not try to shoehorn it into the large functional test
framework it is not designed to be.


-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-19 10:41 ` Cedric Cellier
@ 2018-03-19 10:44   ` Cedric Cellier
  0 siblings, 0 replies; 7+ messages in thread
From: Cedric Cellier @ 2018-03-19 10:44 UTC (permalink / raw)
  To: Bahman Movaqar; +Cc: caml-list

> --- yadayada.ml --- 8< --- 8< ---
> module M = Yadayada_impl : Yadayada_intf.S
> --- >8 --- >8 ---

Bummer, that should have been:

module M : Yadayada_intf.S = Yadayada_impl

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-16 11:12 [Caml-list] On variants, integers and testing Bahman Movaqar
  2018-03-19 10:41 ` Cedric Cellier
@ 2018-03-19 13:27 ` Yawar Amin
  2018-03-19 13:49   ` Yawar Amin
  2018-03-19 21:24 ` SP
  2 siblings, 1 reply; 7+ messages in thread
From: Yawar Amin @ 2018-03-19 13:27 UTC (permalink / raw)
  To: Bahman Movaqar; +Cc: Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 1694 bytes --]

Hi,

On Fri, Mar 16, 2018 at 7:12 AM, Bahman Movaqar <bahman@bahmanm.com> wrote:

> [...]
> Suppose that I wrote this piece of code as a library to be used by others
> as well. In such a case, practically the only function that the users are
> interested in is `solve`, as defined in the .mli file.
> This is good: keeps my library clean, the usage straight-forward and
> doesn't confuse the users.
>
> However, when it comes to testing, things are not that simple. Now that I
> have exported only 1 function in the .mli, I can only test that 1 function.
> Is this the proper way[2]?
>

This is a rather philosophical question. Some people like to test only the
exposed interface, because that's the only thing that's relevant to users.
The internal functionality should be there only to support the
external-facing interface, and thus testing the `solve` function
*thoroughly* should automatically test all internal functionality. If it
doesn't, then maybe that internal functionality shouldn't be there in the
first place?

But, maybe sometimes you do want to have some internal functionality and
you do want to test it. An OCaml can theoretically some of its files
(modules) from the outside world by telling its build system to not expose
the compiled interface (.cmi) files. This way, you can write and test these
internal modules and still hide them from users.

I haven't actually usec this technique, but certainly someone in this list
might have.

Regards,

Yawar

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 2284 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-19 13:27 ` Yawar Amin
@ 2018-03-19 13:49   ` Yawar Amin
  0 siblings, 0 replies; 7+ messages in thread
From: Yawar Amin @ 2018-03-19 13:49 UTC (permalink / raw)
  To: Bahman Movaqar; +Cc: Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 919 bytes --]

Hi,

On Mon, Mar 19, 2018 at 9:27 AM, Yawar Amin <yawar.amin@gmail.com> wrote:

> [...]
>
> But, maybe sometimes you do want to have some internal functionality and
> you do want to test it. An OCaml can theoretically some of its files
> (modules) from the outside world by telling its build system to not expose
> the compiled interface (.cmi) files. This way, you can write and test these
> internal modules and still hide them from users.
>
> I haven't actually usec this technique, but certainly someone in this list
> might have.
>

Actually it looks like we're in luck: jbuilder now supports inline tests
out of the box https://discuss.ocaml.org/t/jbuilder-inline-tests/1741

Regards,

Yawar

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 1276 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-16 11:12 [Caml-list] On variants, integers and testing Bahman Movaqar
  2018-03-19 10:41 ` Cedric Cellier
  2018-03-19 13:27 ` Yawar Amin
@ 2018-03-19 21:24 ` SP
  2018-03-21 14:36   ` Lukasz Stafiniak
  2 siblings, 1 reply; 7+ messages in thread
From: SP @ 2018-03-19 21:24 UTC (permalink / raw)
  To: Bahman Movaqar; +Cc: caml-list

On Fri, Mar 16, 2018 at 12:12:56PM +0100, Bahman Movaqar wrote:
>To limit the values possible for a card's actual value, I defined `Value`
>module (line 6) which basically maps a variant to integer values.
>Is this the idiomatic approach? Is there something like Java's enum or
>Pascal's subranges that I could use[1]?

Sicne I didn't notice anyone else answering this, yes the reason and way you wrote Value looks normal. There are preprocessors that can automate repetitive mappings, but I don't think they are an option to consider lightly.

The rest of the code looked normal too, but I'm not familiar with the domain to help more.

-- 
	SP

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] On variants, integers and testing
  2018-03-19 21:24 ` SP
@ 2018-03-21 14:36   ` Lukasz Stafiniak
  0 siblings, 0 replies; 7+ messages in thread
From: Lukasz Stafiniak @ 2018-03-21 14:36 UTC (permalink / raw)
  To: SP; +Cc: Bahman Movaqar, Caml

[-- Attachment #1: Type: text/plain, Size: 1321 bytes --]

You could also consider private type abbreviations:

https://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec236

On Mon, Mar 19, 2018 at 10:24 PM, SP <sp@orbitalfox.eu> wrote:

> On Fri, Mar 16, 2018 at 12:12:56PM +0100, Bahman Movaqar wrote:
>
>> To limit the values possible for a card's actual value, I defined `Value`
>> module (line 6) which basically maps a variant to integer values.
>> Is this the idiomatic approach? Is there something like Java's enum or
>> Pascal's subranges that I could use[1]?
>>
>
> Sicne I didn't notice anyone else answering this, yes the reason and way
> you wrote Value looks normal. There are preprocessors that can automate
> repetitive mappings, but I don't think they are an option to consider
> lightly.
>
> The rest of the code looked normal too, but I'm not familiar with the
> domain to help more.
>
> --
>         SP
>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 2092 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-03-21 14:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-16 11:12 [Caml-list] On variants, integers and testing Bahman Movaqar
2018-03-19 10:41 ` Cedric Cellier
2018-03-19 10:44   ` Cedric Cellier
2018-03-19 13:27 ` Yawar Amin
2018-03-19 13:49   ` Yawar Amin
2018-03-19 21:24 ` SP
2018-03-21 14:36   ` Lukasz Stafiniak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).