Subtyping and Module Inclusion in OCaml - module

Suppose I have the following setup
module type FOO = sig type f val do_foo : f end
module type BAR = sig type b val do_bar : b end
module type FOOANDBAR =
sig
include FOO
include BAR
end
Now I want to (in a nice way, aka, without copying the interface and so that FOO and BAR are still subtypes) enforce the restriction that the type f and the type b are the same.
Is there a nice way to do this in OCaml, possibly using some different approach that the include keyword?
thanks!!
-Joseph

module type FOOANDBAR =
sig
include FOO
include (BAR with type b = f)
end

Related

Can I avoid lower-case global variables being shadowed in types?

The following code compiles okay in Idris2:
C : Nat
C = 2
claim : C = 2
claim = Refl
but it fails if C is not capitalized:
c : Nat
c = 2
claim : c = 2
claim = Refl
The error message is
Warning: We are about to implicitly bind the following lowercase names.
You may be unintentionally shadowing the associated global definitions:
c is shadowing Main.c
Error: While processing right hand side of claim. When unifying:
2 = 2
and:
c = 2
Mismatch between: 2 and c.
Is there a way to tell Idris compiler not to shadow lowercase global names in types?
I don't know if there's a compiler option or the like, but you can qualify c. If it's in module Foo, use
c : Nat
c = 2
claim : Foo.c = 2
claim = Refl

Is there any use case for an anonymous OCaml structure

The OCaml manual, Chapter 2, says
a structure and is introduced by the struct…end construct, which contains an arbitrary sequence of definitions. The structure is usually given a name with the module binding.
Is there any use case for the creating a struct and not giving it a module name.
If not, then we always use
module Name =
struct
...
end
and so the struct keyword seems a bit redundant.
It's possible and even common (in my code at least) to use nameless structures. One example:
module MyStrSet =
Set.Make(struct type t = string let compare a b = compare b a end)
To expand slightly on Jeffrey's answer, an OCaml functor maps a module to another module. It doesn't care about the module's name.
Consider the following trivial example.
module type SIG =
sig
val x : int
end
module A (B : SIG) =
struct
let y = B.x * 2
end
I've defined a functor A which takes a module B that fulfills the module type SIG. Now, I could define a module Twenty_one that supplies an x value of 21, and then give that to the functor A to create module C.
module Twenty_one =
struct
let x = 21
end
module C = A (Twenty_one)
Or I could directly use an anonymous structure.
module C = A (struct let x = 21 end)
We don't even need to name SIG.
module A (B : sig val x : int end) =
struct
let y = B.x * 2
end
module C = A (struct let x = 21 end)
Strongly into opinion territory, but you may want to give these things names in your code, if it aids with reuse and expressivess.
E.g.
module Int =
struct
type t = int
let compare = compare
end
module Int_map = Map.Make (Int)
Vs.
module Int_map = Map.Make (struct type t = int let compare = compare end)
Another thing you can do with an anonymous structure, that's more relevant to recent (as of 4.08.0) OCaml, is the ability to use open with it, for a syntactically-cheap way to hide names in your namespace (until you write an interface file anyway):
open struct
type hidden_type = string
let hidden_name = 42
end
This feature is called generalized-open, and the relevant manual page for it is here.

How can one specify the value type for an OCaml map

I want to declare ahead of time the value type for a map type.
The functor Map.Make returns a Map.S with two type definitions:
type key
type !+'a t
Type 'a appears to be the type of values in the map. For example, this is the function for adding a key (of type key and value of type 'a:
val add: key -> 'a -> 'a t -> 'a t
One can write the key type like this:
module type M = Map.S with type key = string
But I couldn't figure out how to specify the value type. This isn't valid syntax:
module type M = Map.S with type key = string and 'a = int
One way to look at this is that you're trying to impose monomorphism in the wrong place. The essence of Map.S is that it's polymorphic in the element type.
You can easily define a type for maps from string keys to int values:
# module M = Map.Make(String);;
. . .
# type string_int_mod = int M.t;;
type string_int_mod = int M.t
# let f (m: string_int_mod) s i = M.add s i m;;
val f : string_int_mod -> M.key -> int -> int M.t = <fun>
In many cases, the polymorphism inferred by OCaml is clearer than specifically ascribed types. At least in my opinion. The types inferred by OCaml tell you what the code is really doing and where it has degrees of freedom.

How do you define a non-generic recursive datatype in Idris?

This is literally my first line of Idris code. When I looked up the documentation, all appeared proper:
Idris> data T = Foo Bool | Bar (T -> T)
(input):1:6:
|
1 | data T = Foo Bool | Bar (T -> T)
| ^
unexpected reserved data
expecting dependent type signature
This makes me think I may need to declare T to be a symbol in some fashion?
It works as expected inside an Idris source file. At the REPL however, declarations need to be prefixed with the :let command:
:let data T = Foo Bool | Bar (T -> T)
Thanks for the question. I learned something trying to answer it.

Why can't dependent types in Idris handle this situation?

I want to do the following:
data Foo : (a : Type) -> (b : Type) -> (c : a -> b -> Type) -> Type where
Bar : a -> (c a) -> Foo a b c
but I get the following error:
When checking type of test.Bar:
When checking argument c to test.Foo:
Type mismatch between
Type -> Type (Type of c)
and
a -> b -> Type (Expected type)
Specifically:
Type mismatch between
Type
and
b -> Type
This seems like it should be valid to me. That is c has the correct type in the expression Foo a b c, but Idris thinks it has the type b -> Type, or what I think of as (c a).
Am I missing something, or is this a limitation of Idris?
(c a) has type b -> Type, while all fields of a data constructor must have type Type. It's an error, exactly as Idris says. Your c type constructor takes two arguments but you only applied it to a single a.