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.
Related
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.
I was writing a function with user-defined types in OCaml when I encountered an error message that I don't understand.
I'm currently using the OCaml interactive toplevel and also Visual Studio Code to write my code. The strange thing is that when I run the code in Visual Studio Code, it compiles fine but encounters the error in the interactive toplevel.
The OCaml code that I am referring to is as follows:
type loc = int;;
type id = string;;
type value =
| Num of int
| Bool of bool
| Unit
| Record of (id -> loc)
;;
type memory = (loc * value) list;;
exception NotInMemory;;
let rec memory_lookup : (memory * loc) -> value
= fun (mem, l) ->
match mem with
| [] -> raise NotInMemory
| hd :: tl -> (match hd with
| (x, a) -> if x = l then a else (memory_lookup (tl, l))
)
;;
The code that I wrote is basically my rudimentary attempt at implementing/emulating looking up memory and returning corresponding values.
Here's an example input:
memory1 = [ (1, Num 1) ; (2, Bool true) ; (3, Unit) ];;
Here's the expected output:
memory_lookup (memory1, 2);;
- : value = Bool true
However, here's the actual output:
Characters: 179-180:
| (x, a) -> if x = l then "a" else (memory_lookup (tl, l)))
Error: This expression has type value/1076
but an expression was expected of type value/1104
(Just for clarification: the error is regarding character a)
Does anybody know what type value/1076 and type value/1104 mean? Also, if there is anything wrong with the code that I wrote, would anybody be kind enough to point it out?
Thank you.
This kind of error happens in the toplevel when a type is defined multiple times, and some values of the old type are left in scope. A simple example is
type t = A
let x = A;;
type t = A
let y = A;;
x = y;;
Error: This expression has type t/1012 but an expression was expected of type
t/1009
The numerical part after the type name in value/1076 is a binding time for the type value. This binding time is used as a last resort to differentiate between two different types that happens to have the same name. Thus
Error: This expression has type value/1076
but an expression was expected of type value/1104
means that the value memory1 was defined with a type value defined at time 1076, whereas the function memory_lookup expected values of the type value defined at a later date (aka at time 1104). The binding times are a bit arbitrary , so they may be replaced by simply value/1 and value/2 in OCaml 4.08 .
Just started Haskell, it's said that everything in Haskell is "immutable" except IO package. So when I bind a name to something, it's always something immutable? Question, like below:
Prelude> let removeLower x=[c|c<-x, c `elem` ['A'..'Z']]
Prelude> removeLower "aseruiiUIUIdkf"
"UIUI"
So here:
1. “removeLower" is an immutable? Even it's a function object?
But I can still use "let" to assign something else to this name.
2. inside the function "c<-x" seems that "c" is a variable.
It is assigned by list x's values.
I'm using the word "variable" from C language, not sure how Haskell name all its names?
Thanks.
If you're familiar with C, think of the distinction between declaring a variable and assigning a value to it. For example, you can declare a variable on its own and later assign to it:
int i;
i = 7;
Or you can declare a variable and assign initial value at the same time:
int i = 7;
And in either case, you can mutate the value of a variable by assigning to it once more after the first initialization or assignment:
int i = 7; // Declaration and initial assignment
i = 5; // Mutation
Assignment in Haskell works exclusively like the second example—declaration with initialization:
You declare a variable;
Haskell doesn't allow uninitialized variables, so you are required to supply a value in the declaration;
There's no mutation, so the value given in the declaration will be the only value for that variable throughout its scope.
I bolded and hyperlinked "scope" because it's the second critical component here. This goes one of your questions:
“removeLower" is an immutable? Even it's a function object? But I can still use "let" to assign something else to this name.
After you bind removeLower to the function you define in your example, the name removeLower will always refer to that function within the scope of that definition. This is easy to demonstrate in the interpreter. First, let's define a function foo:
Prelude> let foo x = x + 2
Prelude> foo 4
6
Now we define an bar that uses foo:
Prelude> let bar x = foo (foo x)
Prelude> bar 4
8
And now we "redefine" foo to something different:
Prelude> let foo x = x + 3
Prelude> foo 4
7
Now what do you think happens to bar?
Prelude> bar 4
8
It remains the same! Because the "redefinition" of foo doesn't mutate anything—it just says that, in the new scope created by the "redefinition", the name foo stands for the function that adds three. The definition of bar was made in the earlier scope where foo x = x + 2, so that's the meaning that the name foo has in that definition of bar. The original value of foo was not destroyed or mutated by the "redefinition."
In a Haskell program as much as in a C program, the same name can still refer to different values in different scopes of the program. This is what makes "variables" variable. The difference is that in Haskell you can never mutate the value of a variable within one scope. You can shadow a definition, however—uses of a variable will refer to the "nearest" definition of that name in some sense. (In the case of the interpreter, the most recent let declaration for that variable.)
Now, with that out of the way, here are the syntaxes that exist in Haskell for variable binding ("assignment"). First, there's top-level declarations in a module:
module MyLibrary (addTwo) where
addTwo :: Int -> Int
addTwo x = x + 2
Here the name addTwo is declared with the given function as its value. A top level declaration can have private, auxiliary declarations in a where block:
addSquares :: Integer -> Integer
addSquares x y = squareOfX + squareOfY
where square z = z * z
squareOfX = square x
squareOfY = square y
Then there's the let ... in ... expression, that allows you to declare a local variable for any expression:
addSquares :: Integer -> Integer
addSquares x y =
let square z = z * z
squareOfX = square x
squareOfY = square y
in squareOfX + squareOfY
Then there's the do-notation that has its own syntax for declaring variables:
example :: IO ()
example = do
putStrLn "Enter your first name:"
firstName <- getLine
putStrLn "Enter your lasst name:"
lastName <- getLine
let fullName = firstName ++ " " ++ lastName
putStrLn ("Hello, " ++ fullName ++ "!")
The var <- action assigns a value that is produced by an action (e.g., reading a line from standard input), while let var = expr assigns a value that is produced by a function (e.g., concatenating some strings). Note that the let in a do block is not the same thing as the let ... in ... from above!
And finally, in list comprehension you get the same assignment syntax as in do-notation.
It's referring to the monadic bind operator >>=. You just don't need to explicitly write a lambda as right hand side parameter. The list comprension will be compiled down to the monadic actions defined. And by that it means exactly the same as in a monadic environment.
In fact you can replace the list comprension with a simple call to filter:
filter (`elem` ['A' .. 'Z']) x
To answer your question regarding the <- syntactic structure a bit clearer:
[c| c <- x]
is the same as
do c <- x
return c
is the same as
x >>= \c -> return c
is the same as
x >>= return
Consider the official documentation of Haskell for further reading: https://hackage.haskell.org/package/base-4.8.2.0/docs/Control-Monad.html#v:-62--62--61-
[c|c<-x, c `elem` ['A'..'Z']]
is a list comprehension, and c <- x is a generator where c is a pattern to be matched from the elements of the list x. c is a pattern which is successively bound to the elements of the input list x which are a, s, e, u, ... when you evaluate removeLower "aseruiiUIUIdkf".
c `elem` ['A'..'Z']
is a predicate which is applied to each successive binding of c inside the comprehension and an element of the input only appears in the output list if it passes this predicate.
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
I have a case class which takes a list of functions:
case class A(q:Double, r:Double, s:Double, l:List[(Double)=>Double])
I have over 20 functions defined. Some of these functions have their own parameters, and some of them also use the q, r, and s values from the case class. Two examples are:
def f1(w:Double) = (d:Double) => math.sin(d) * w
def f2(w:Double, q:Double) = (d:Double) => d * q * w
The problem is that I then need to reference q, r, and s twice when instantiating the case class:
A(0.5, 1.0, 2.0, List(f1(3.0), f2(4.0, 0.5))) //0.5 is referenced twice
I would like to be able to instantiate the class like this:
A(0.5, 1.0, 2.0, List(f1(3.0), f2(4.0))) //f2 already knows about q!
What is the best technique to accomplish this? Can I define my functions in a trait that the case class extends?
EDIT: The real world application has 7 members, not 3. Only a small number of the functions need access to the members. Most of the functions don't care about them.
If q in f2 is always referring to the q in you case class, then one quick hack :
trait TraitA {
def q:Double
def r:Double
def s:Double
def f1(w:Double) = (d:Double) => math.sin(d) * w
def f2(w:Double) = (d:Double) => d * q * w
}
case class A(q:Double, r:Double, s:Double, l:List[(Double)=>Double]=Nil) extends TraitA
val a=new A(0.5, 1.0, 2.0){override val l= List(f1(3.0), f2(4.0))}
There's the obvious val declaration:
val a = 0.5
A(a, 1.0, 2.0, List(f1(3.0), f2(4.0, a)))
Otherwise, f2 needs a reference to A's this, which it will have if it's a member of class A or that particular instance of A. Part of the problem is that the functions are fully baked before the instance of A is instantiated. So you have to define f2, as opposed to simply instantiate it, in the context of A.
Finally, you could make the functions partial functions. The first group of params will be as they are, but a second group will be added that is of type A.
One simple idea would be to change the function to take a list of functions that take 3 doubles (q, r, and s) and return a function from double to double. That way those functions that need any of the values can use them, and others just ignore them all.