I'm having trouble understanding function type signatures for higher-order functions in OCaml.
fun f -> f 3
(int -> a) -> a
The way I process this is that f 3 part takes an int as input and returns the type defined by the function f which is denoted as a. So really, fun f is a type (int->a). But then where is the last a coming from in (int -> a) -> a?
Your first example is this:
fun f -> f 3
I think that one possible confusion you might be having is that you're thinking of this as the definition of a function named f. This is not the case. This is an anonymous value representing a function, also known as a lambda. The f represents the paramter of this anonymous function.
To keep things clearer, let's give the function the name g. In other words, assume that we define g like this:
let g = fun f -> f 3
OK, so g is a function that takes one parameter f. This f parameter is obvously a function since we see it being applied to 3. (I.e., we see it being called with 3 as the argument.) What does g return? It returns whatever f returns when you call it, right?
Since g is a function its type must be something of this form:
d -> c
I.e., it accepts something of type d and returns something of type c. From the reasoning above, we know that d is a function type, and we also know that the return type of this function is also the return type of g. So if d is (in more detail) b -> a, then the full type of g is like this:
(b -> a) -> a
However we also know that the function parameter f takes an int argument because we see it being applied to 3. So the type b must be int. This gives us the following for the type of g:
(int -> a) -> a
I hope this helps make things clearer.
We could annotate the anonymous function thus:
fun (f : int -> 'a) -> (f 3 : 'a)
I.e., it's a function from f : int -> 'a to 'a, so this is where your last 'a is coming from.
Related
With QuickCheck, one can write parametrically polymorphic properties, like this:
associativityLaw :: (Eq a, Show a, Semigroup a) => a -> a -> a -> Property
associativityLaw x y z = (x <> y) <> z === x <> (y <> z)
This is just an example, as my actual properties are more complex, but it illustrates the problem well enough. This property verifies that for a type a, the <> operator is associative.
Imagine that I'd like to exercise this property for more than one type. I could define my test list like this:
tests =
[
testGroup "Monoid laws" [
testProperty "Associativity law, [Int]" (associativityLaw :: [Int] -> [Int] -> [Int] -> Property),
testProperty "Associativity law, Sum Int" (associativityLaw :: Sum Int -> Sum Int -> Sum Int -> Property)
]
]
This works, but feels unnecessarily verbose. I'd like to be able to simply state that for a given property, a should be [Int], or a should be Sum Int.
Something like this hypothetical syntax:
testProperty "Associativity law, [Int]" (associativityLaw :: a = [Int]),
testProperty "Associativity law, Sum Int" (associativityLaw :: a = Sum Int)
Is there a way to do this, perhaps with a GHC language extension?
My actual problem involves higher-kinded types, and I'd like to be able to state that e.g. f a is [Int], or f a is Maybe String.
I'm aware of this answer, but both options (Proxy and Tagged) seem, as described there, at least, too awkward to really address the issue.
You can use TypeApplications to bind type variables like this:
{-# LANGUAGE TypeApplications #-}
associativityLaw #[Int]
In the case you mentioned where you have a higher kinded type and you want to bind f a to [Int], you have to bind the type variables f and a separately:
fmap #[] #Int
For functions with more than one type variable, you can apply the args in order:
f :: a -> b -> Int
-- bind both type vars
f #Int #String
-- bind just the first type var, and let GHC infer the second one
f #Int
-- bind just the second type var, and let GHC infer the first one
f #_ #String
Sometimes the "order" of the type variables may not be obvious, but you can use :type +v and ask GHCi for more info:
λ> :t +v traverse
traverse
:: Traversable t =>
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> t a -> f (t b)
In standard haskell, the "order" of the type variables doesn't matter, so GHC just makes one up for you. But in the presence of TypeApplications, the order does matter:
map :: forall b a. (a -> b) -> ([a] -> [b])
-- is not the same as
map :: forall a b. (a -> b) -> ([a] -> [b])
For this reason, when working with highly parametric code, or you expect your users are going to want to use TypeApplications on your functions, you might want to explicitly set the order of your type vars instead of letting GHC define an order for you, with ExplicitForAll:
{-# LANGUAGE ExplicitForAll #-}
map :: forall a b. (a -> b) -> ([a] -> [b])
Which feels a lot like <T1, T2> in java or c#
I'm new to functional programming and I'm trying to implement a basic algorithm using OCAML for course that I'm following currently.
I'm trying to implement the following algorithm :
Entries :
- E : a non-empty set of integers
- s : an integer
- d : a positive float different of 0
Output :
- T : a set of integers included into E
m <- min(E)
T <- {m}
FOR EACH e ∈ sort_ascending(E \ {m}) DO
IF e > (1+d)m AND e <= s THEN
T <- T U {e}
m <- e
RETURN T
let f = fun (l: int list) (s: int) (d: float) ->
List.fold_left (fun acc x -> if ... then (list_union acc [x]) else acc)
[(list_min l)] (list_sort_ascending l) ;;
So far, this is what I have, but I don't know how to handle the modification of the "m" variable mentioned in the algorithm... So I need help to understand what is the best way to implement the algorithm, maybe I'm not gone in the right direction.
Thanks by advance to anyone who will take time to help me !
The basic trick of functional programming is that although you can't modify the values of any variables, you can call a function with different arguments. In the initial stages of switching away from imperative ways of thinking, you can imagine making every variable you want to modify into the parameters of your function. To modify the variables, you call the function recursively with the desired new values.
This technique will work for "modifying" the variable m. Think of m as a function parameter instead.
You are already using this technique with acc. Each call inside the fold gets the old value of acc and returns the new value, which is then passed to the function again. You might imagine having both acc and m as parameters of this inner function.
Assuming list_min is defined you should think the problem methodically. Let's say you represent a set with a list. Your function takes this set and some arguments and returns a subset of the original set, given the elements meet certain conditions.
Now, when I read this for the first time, List.filter automatically came to my mind.
List.filter : ('a -> bool) -> 'a list -> 'a list
But you wanted to modify the m so this wouldn't be useful. It's important to know when you can use library functions and when you really need to create your own functions from scratch. You could clearly use filter while handling m as a reference but it wouldn't be the functional way.
First let's focus on your predicate:
fun s d m e -> (float e) > (1. +. d)*.(float m) && (e <= s)
Note that +. and *. are the plus and product functions for floats, and float is a function that casts an int to float.
Let's say the function predicate is that predicate I just mentioned.
Now, this is also a matter of opinion. In my experience I wouldn't use fold_left just because it's just complicated and not necessary.
So let's begin with my idea of the code:
let m = list_min l;;
So this is the initial m
Then I will define an auxiliary function that reads the m as an argument, with l as your original set, and s, d and m the variables you used in your original imperative code.
let rec f' l s d m =
match l with
| [] -> []
| x :: xs -> if (predicate s d m x) then begin
x :: (f' xs s d x)
end
else
f' xs s d m in
f' l s d m
Then for each element of your set, you check if it satisfies the predicate, and if it does, you call the function again but you replace the value of m with x.
Finally you could just call f' from a function f:
let f (l: int list) (s: int) (d: float) =
let m = list_min l in
f' l s d m
Be careful when creating a function like your list_min, what would happen if the list was empty? Normally you would use the Option type to handle those cases but you assumed you're dealing with a non-empty set so that's great.
When doing functional programming it's important to think functional. Pattern matching is super recommended, while pointers/references should be minimal. I hope this is useful. Contact me if you any other doubt or recommendation.
In Ocaml you can introduce new type variables inside a constraint, which is useful to enforce type-identities in the type-checker:
let f g n = (g (n:'n):'n) ;;
val f : ('n -> 'n) -> 'n -> 'n = <fun>
It is obviously possible to re-use these type variables (otherwise it would be a rather pointless exercise). However, since they are not introduced by some special statement, I wonder what there scope is? Is it the enclosing function, let-binding or top-level statement?
Is there a way to limit the scope of such an implicitly introduced type-variable?
A scope of any type variable used in a type constraint is the body of the enclosing let-expression. If an expression is mutually recursive, then the scope is extended to the whole set of mutual recursive expressions. The scope cannot be reduced. Let-expression is a typing primitive. It is not possible to hide or override a type variable.
Whenever a new type variable is introduced, it is looked up in a current typing context. If it was already introduced, then it is unified. Otherwise a new type variable is added to the context. (That can be later used for unification).
An example to clarify the idea:
let rec f g h x y = g (x : 'a) + h (y : 'a) and e (x : 'a) = x + 1;;
Here, 'a used to constraint x in e is the same 'a that was used to contraint x and y in the body of function f. Since, x in e is unified with int type the unification extends to function f, constraining function g and h to type int -> int.
I've got a library which implements a set (interface with documentation available here: http://pastebin.com/j9QUyN1G). I understand everything apart from this fragment:
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f s] applies [f] to all elements in set [s]. The elements
are passed to [f] in increasing order with respect to the ordering
used to create the set. *)
So iter takes a function as one of the arguements and applies it to all elements of set. So I would expect something like ('a -> 'a) which takes an element of the set and changes it to element of the same type with other value or ('a -> 'b) which takes 'a t and transforms it to 'b t. But instead iter takes a function of type ('a -> unit) and also returns unit, not an 'a t nor 'b t.
So how should an example function passed to iter look like?
iter doesn't change the elements of the set. It's executed purely for its side effects. You might use it to print the elements, for example:
module StringSet = Set.Make(String)
…
StringSet.iter print_endline ss
The set data structure is immutable, so you can't change the elements of the set. You can build a new set whose elements are derived from an existing set. For a list, there's the function map which takes a list [x1; …; xn] and returns a new list [f x1; …; f xn]. There is no similar function in the Set module because elements in a set are not stored in the order chosen by the caller: there's no such thing as a set with its elements in an order derived from another set. If you want to build a set from the images of the elements of a set, insert the new elements one by one.
module Int = struct
type t = int
let compare = Pervasives.compare
end
module IntSet = Set.Make(Int)
module StringSet = Set.Make(String)
let int_to_string_set is =
IntSet.fold (fun i ss -> StringSet.add (string_of_int i) ss) is StringSet.empty
iter takes such function that accepts argument of type 'a do with it whatever it whats and returns a value of type unit. In other words it is evaluated for the side-effects since it can't return anything worthwhile.
What you're looking for is a map function, that usually accepts a function of type 'a -> 'b a container with elements of type 'a and returns an container with elements of type 'b. Unfortunately to you, the interface you've shown, doesn't provide such function. But this is not a problem, since it provides a fold function, that is the most general iterator. Having only fold you can implement any other iteratos, like map, iter, exists, etc... Indeed in Core library you can find Container.Make functor that will automatically derive a common container interface from only one function - fold. But also, you can define map by yourself:
let map f xs =
fold (fun x ys -> add (f x) ys) xs empty
It would be a function with side effects, like this:
Let p x = Printf.printf "%d\n" x
This is part of a homework assignment so my goal is to understand why this is wrong. As I mentioned before I'm using Moscow ML.
fun filter pred = let
fun f ([], a) = []
| f ([], a) = a
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
in
f
end
The error I get is:
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
^
Type clash: expression of type
'a list cannot have type
'a list * 'b list
I have been reading up on documentation, and it really hasn't helped. What I really don't get is where 'b list is coming from. In our assignment we have to use an accumulator with tail recursion. I believe where my error is is how filter calls the function f. Filter takes the predicate as an argument and f should take the list and accumulator which is initially the empty list.
I've tried calling f like: f L [], But in other examples we didn't actually have to call f with its argument and it was somehow passed automatically.
Anyway, any help understanding where my mistake is and guidance on how to fix the problem would be greatly appreciated.
-aitee
(also if anyone could give me any tips on decoding the type expression errors that could also be very beneficial.)
(f L (e::a)) would work only if f were a curried function, of type 'a list -> 'a list -> 'a list. You should be doing:
if pred e then (f (L, (e::a))) else (f (L,a))
Btw., SMLNJ complains of a redundant match (two f ([], a) clauses are given).
You're confusing tupled versus curried function calls. Your definition of f demands a tuple, (a,b), but you're passing it arguments as f a b. Try replacing your recursive calls to f L ... with f (L,...) instead.
The type error is a little unhelpful, but it's basically saying that you're passing a list when it expects a 2-tuple of lists.