ocaml order of parameters for fold - ocaml

I executed the following command in utop with Jane street Base library installed
open Base;;
List.fold;;
It prints
- : 'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum = <fun>
I interpret this as the fold function first parameter is a list of values. second is the initial value and 3rd is the fold function. The folder function whose first parameter is the accumulator and second parameter is the item from the list being folded.
With this interpretation I write this code
List.fold [Some 1; None; None; Some 2] 0 (fun accm x -> match x with | None -> accum | Some x -> accum + x)
This doesn't work and it prints something weird on the screen
- : init:(int -> (int -> int option -> int) -> '_weak2) ->
f:((int -> (int -> int option -> int) -> '_weak2) ->
int option -> int -> (int -> int option -> int) -> '_weak2) ->
'_weak2
= <fun>
Now If I change my code in utop to use named parameters
List.fold [Some 1; None; Some 2] ~init:0 ~f:(fun accum x -> match x with | None -> accum | Some x -> accum + x);;
Now it works. What's going on? I passed the parameters in the same order as the documented signature suggested? then why am I being forced to use named parameters?

Argument labels can only be omitted in non-ambiguous full applications.
In particular, this is never the case for labelled functions with a polymorphic return type like fold. Indeed, for such function, there is no clear notion of full application.
For instance, if you look at your initial application:
List.fold [Some 1; None; None; Some 2] 0
(fun accm x -> match x with | None -> accum | Some x -> accum + x)
it could be completed into the following full application:
List.fold
[Some 1; None; None; Some 2] 0
(fun acc x -> match x with None -> acc | Some x -> acc + x)
~init:(fun x f -> f x None)
~f:(fun f _ -> f )
Consequently, your initial code
List.fold [Some 1; None; None; Some 2] 0
(fun accm x -> match x with | None -> accum | Some x -> accum + x)
is not a full application, but a valid partial application where the labelled arguments are still missing.

I'm going to guess you're using the Jana Street base library. So let's start with a link to those docs..
The List.fold in that library does accept the init value and the function to run as named parameters. You have not provided those named parameters in:
List.fold [Some 1; None; None; Some 2] 0 (fun accm x -> match x with | None -> accum | Some x -> accum + x)
If you try partially applying:
List.fold [Some 1; None; None; Some 2]
You will see:
- : init:'_weak2 -> f:('_weak2 -> int option -> '_weak2) -> '_weak2 = <fun>
This is a new function with lots of weak polymorphic types. Jeffrey in particular has written extensively on this subject on Stack Overflow. One example: https://stackoverflow.com/a/25798225/15261315.
You're then applying it to the value 0, which yields:
- : init:(int -> '_weak3) ->
f:((int -> '_weak3) -> int option -> int -> '_weak3) -> '_weak3
We can see this with a simple function of our own devising:
utop # let f a ~b ~g = g a b;;
val f : 'a -> b:'b -> g:('a -> 'b -> 'c) -> 'c = <fun>
utop # f 5;;
- : b:'_weak4 -> g:(int -> '_weak4 -> '_weak5) -> '_weak5 = <fun>
utop # f 5 6;;
- : b:'_weak6 -> g:(int -> '_weak6 -> int -> '_weak7) -> '_weak7 = <fun>

Related

How to define "apply" in OCaml

I am trying to define a function that is similar to Lisp's apply. Here is my attempt:
type t =
| Str of string
| Int of int
let rec apply f args =
match args with
| (Str s)::xs -> apply (f s) xs
| (Int i)::xs -> apply (f i) xs
| [] -> f
(* Example 1 *)
let total = apply (fun x y z -> x + y + z)
[Int 1; Int 2; Int 3]
(* Example 2 *)
let () = apply (fun name age ->
Printf.printf "Name: %s\n" name;
Printf.printf "Age: %i\n" age)
[Str "Bob"; Int 99]
However, this fails to compile. The compiler gives this error message:
File "./myprog.ml", line 7, characters 25-30:
7 | | (Str s)::xs -> apply (f s) xs
^^^^^
Error: This expression has type 'a but an expression was expected of type
string -> 'a
The type variable 'a occurs inside string -> 'a
What is the meaning of this error message? How can I fix the problem and implement apply?
You cannot mix an untyped DSL for data:
type t =
| Int of int
| Float of float
and a shallow embedding (using OCaml functions as functions inside the DSL) for functions in apply
let rec apply f args =
match args with
| (Str s)::xs -> apply (f s) xs (* f is int -> 'a *)
| (Int i)::xs -> apply (f i) xs (* f is string -> 'a *)
| [] -> f (* f is 'a *)
The typechecker is complaining that if f has type 'a, f s cannot also have for type 'a since it would mean that f has simultaneously type string -> 'a and 'a (without using the recursive types flag).
And more generally, your function apply doesn't use f with a coherent type: sometimes it has type 'a, sometimes it has type int -> 'a, other times it would rather have type string -> 'a. In other words, it is not possible to write a type for apply
val apply: ??? (* (int|string) -> ... *) -> t list -> ???
You have to choose your poison.
Either go with a fully untyped DSL which contains functions, that can be applied:
type t =
| Int of int
| Float of float
| Fun of (t -> t)
exception Type_error
let rec apply f l = match f, l with
| x, [] -> f
| Fun f, a :: q -> apply (f a) q
| (Int _|Float _), _ :: _ -> raise Type_error
or use OCaml type system and define a well-typed list of arguments with a GADT:
type ('a,'b) t =
| Nil: ('a,'a) t
| Cons: 'a * ('b,'r) t -> ('a -> 'b,'r) t
let rec apply: type f r. f -> (f,r) t -> r = fun f l ->
match l with
| Nil -> f
| Cons (x,l) -> apply (f x) l
EDIT:
Using the GADT solution is quite direct since we are using usual OCaml type without much wrapping:
let three = apply (+) (Cons(1, Cons(2,Nil)))
(and we could use a heterogeneous list syntactic sugar to make this form even lighter syntactically)
The untyped DSL requires to build first a function in the DSL:
let plus = Fun(function
| Float _ | Fun _ -> raise Type_error
| Int x -> Fun(function
| Float _ | Fun _ -> raise Type_error
| Int y -> Int (x+y)
)
)
but once we have built the function, it is relatively straightforward:
let three = apply_dsl plus [Int 2; Int 1]
type t =
| Str of string
| Int of int
| Unit
let rec apply f args =
match args with
| x::xs -> apply (f x) xs
| [] -> f Unit
Let's go step by step:
line 1: apply : 'a -> 'b -> 'c (we don't know the types of f, args and apply's return type
line 2 and beginning of line 3: args : t list so apply : 'a -> t list -> 'c
rest of line 3: Since f s (s : string), f : string -> 'a but f t : f because apply (f s). This means that f contains f in its type, this is a buggy behaviour
It's actually buggy to call f on s and i because this means that f can take a string or an int, the compiler will not allow it.
And lastly, if args is empty, you return f so the return type of f is the type of f itself, another buggy part of this code.
Looking at your examples, a simple solution would be:
type t = Str of string | Int of int
let rec apply f acc args =
match args with x :: xs -> apply f (f acc x) xs | [] -> acc
(* Example 1 *)
let total =
apply
(fun acc x ->
match x with Int d -> d + acc | Str _ -> failwith "Type error")
0 [ Int 1; Int 2; Int 3 ]
(* Example 2 *)
let () =
apply
(fun () -> function
| Str name -> Printf.printf "Name: %s\n" name
| Int age -> Printf.printf "Age: %i\n" age)
() [ Str "Bob"; Int 99 ]
Since you know the type you want to work on, you don't need GADT shenanigans, just let f handle the pattern matching and work with an accumulator

Please explain the ppx_variants_conv make_matcher method signature

I found myself wanting a way to do some codegen around some large variant types in my code, and I found ppx_variants_conv (https://github.com/janestreet/ppx_variants_conv)
The make_matcher method sounds potentially useful to me, but there are no docs and tbh I am struggling to read the example signature:
val make_matcher :
a:(('a -> 'a t) Variant.t -> 'b -> ('c -> 'd) * 'e)
-> b:((char -> 'f t) Variant.t -> 'e -> (char -> 'd) * 'g)
-> c:('h t Variant.t -> 'g -> (unit -> 'd) * 'i)
-> d:((int -> int -> 'j t) Variant.t -> 'i -> (int -> int -> 'd) * 'k)
-> 'b
-> ('c t -> 'd) * 'k
a b c and d labelled arguments correspond to the cases of the variant and the first part of each signature corresponds to the constructor for each case... I get a bit lost after that 🤔
and it seems a odd to me that 'b 'c 'd and 'k appear in the latter part of the signature but not 'e 'f 'g 'h 'i 'j
In the make_matcher function each labeled argument takes a function of two arguments that has a general form, fun v x -> f, y, where v is the first-class variant that represents the corresponding constructor, x is the value that is folded over all matchers-generating functions. The function returns a pair, in which the first constituent, the function f, is actually the matcher that will be called if that variant matches and some value y that will be passed to the next matcher-generating function.
Let's do some examples to illustrate this. First, let's define some simple matcher, e.g.,
type 'a t =
| A of 'a
| B of char
| C
| D of int * int
[##deriving variants]
let matcher init = Variants.make_matcher
~a:(fun v (x1 : char) ->
(fun x -> x+1),Char.code x1)
~b:(fun v (x2 : int) ->
(fun c -> Char.code c),float x2)
~c:(fun v (x3 : float) ->
(fun () -> 0), string_of_float x3)
~d:(fun v (x4 : string) ->
(fun x y -> x + y),[x4])
init
and here's how we can use, it,
# let f,s = matcher '*';;
val f : int t -> int = <fun>
val s : Base.string list = ["42."]
# f (A 10);;
- : int = 11
# f (B '*');;
- : int = 42
# f C;;
- : int = 0
# f (D (1,2));;
- : int = 3
To be honest, I don't know the purpose of the extra parameter that is passed to each matcher-generating function1. Probably, the idea is that depending on the initial parameter we could generate different matchers. But if you don't need this, then just pass () to it and/or define your own simplified matcher that ignores this additional information, e.g.,
let make_simple_matcher ~a ~b ~c ~d =
fst ##Variants.make_matcher
~a:(fun _ _ -> a,())
~b:(fun _ _ -> b,())
~c:(fun _ _ -> c,())
~d:(fun _ _ -> d,())
()
The make_simple_matcher function has an expected type,
a:('a -> 'b) ->
b:(char -> 'b) ->
c:(unit -> 'b) ->
d:(int -> int -> 'b) ->
'a t -> 'b
1) looking into the guts of the code that generates this function doesn't help a lot, as they use the generic name acc for this parameter, which is not very helpful.

F# Writing custom foldback function for list

I am learning F#. I have written custom fold function for list (with help here on StackOverflow). I am now trying to write foldback function say myOwnFoldBack. The expected output might be myOwnFoldBack (+) 0 [1; 2; 3 ] should return 6.
Here is my code for myOwnFold
let rec myOwnFoldf s0 =
function
| [] -> s0
| x::tail -> myOwnFoldf (f s0 x) tail
This works fine.
Here is code for myOwnFoldBack
let rec myOwnFoldBack f s0 =
function
| [] -> 0
| x::tail -> x f (myOwnFoldBackf tail)
The error I get is:
Type mismatch. Expecting a
'a
but given a
('b -> 'a -> int) list -> int
The resulting type would be infinite when unifying ''a' and '('b -> 'a -> int) list -> int'
I think I figured it out finally!
let rec myOwnFoldBack f s0 =
function
| [] -> s0
| x::tail -> f x (myOwnFoldBack f s0 tail)

How to write a function to count the number of elements in a list?

How can I write a function using fold_left and not using fold to count the number of elements in a list?
I tried
let rec count_elements l c =
match l with
|[] -> c
|h::t -> c = c+1
I don't believe this works, and I am not how to do this using fold_left, any guidance would be appreciated
To add some clarity to the answers, I'd like to stress some things :
fold_left is just a way of doing some operations on a list in a tail-recursive way. The best way to understand fold_left is to do your own implementation of it :
# let fold_left f acc l =
let rec fr acc l =
match l with
| [] -> acc
| hd :: tl -> fr (f acc hd) tl
in fr acc l;;
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
That's exactly what length does when you write
# let length l = List.fold_left (fun c _ -> c + 1) 0 l;;
val length : 'a list -> int = <fun>
What happens is equivalent to :
# let length l =
let rec lr acc l =
match l with
| [] -> acc
| _ :: tl -> lr (acc + 1) tl
in lr 0 l;;
val length : 'a list -> int = <fun>
So, the solution
let rec length l =
match l with
| [] -> 0
| _ :: tl -> 1 + length tl
corresponds to fold_right and is not tail-recursive.
Hoping this will clarify some things for you :-)
Using fold_left, you can do it like this :
# let size l = List.fold_left (fun acc _ -> acc + 1) 0 l;;
val size : 'a list -> int = <fun>
# size [1;2;3];;
- : int = 3
# size [];;
- : int = 0
#
You start with the accumulator 0 and then you add it +1 for every element in the list.

How can I skip a term with List.Map in OCAML?

Suppose I have some code like this:
List.map (fun e -> if (e <> 1) then e + 1 else (*add nothing to the list*))
Is there a way to do this? If so, how?
I want to both manipulate the item if it matches some criteria and ignore it if it does not. Thus List.filter wouldn't seem to be the solution.
SML has a function mapPartial which does exactly this. Sadly this function does not exist in OCaml. However you can easily define it yourself like this:
let map_partial f xs =
let prepend_option x xs = match x with
| None -> xs
| Some x -> x :: xs in
List.rev (List.fold_left (fun acc x -> prepend_option (f x) acc) [] xs)
Usage:
map_partial (fun x -> if x <> 1 then Some (x+1) else None) [0;1;2;3]
will return [1;3;4].
Or you can use filter_map from extlib as ygrek pointed out.
Both Batteries and Extlib provide an equivalent of mapPartial: their extended List module sprovide a filter_map function of the type ('a -> 'b option) -> 'a list -> 'b list, allowing the map function to select items as well.
Another solution would be to use directly a foldl :
let f e l = if (e <> 1)
then (e + 1)::l
else l
in List.fold_left f [] list
But my preference is filter_map as Michael Ekstrand provided
Alternatively you can filter your list then apply the map on the resulted list as follows :
let map_bis predicate map_function lst =
List.map map_function (List.filter predicate lst);;
# val map_bis : ('a -> bool) -> ('a -> 'b) -> 'a list -> 'b list = <fun>
Usage :
# map_bis (fun e -> e<>1) (fun e -> e+1) [0;1;2;3];;
- : int list = [1; 3; 4]
You can also map values to singleton lists if you want to keep them or empty lists if you don't, and then concat the results.
List.concat (List.map (fun e -> if (e <> 1) then [e + 1] else []) my_list)
use
let rec process = function
| 1 :: t -> process t
| h :: t -> (h + 1) :: (process t)
| [] -> []
or tail recursive
let process =
let rec f acc = function
| 1 :: t -> f acc t
| h :: t -> f ((h + 1) :: acc) t
| [] -> List.rev acc in
f []
or with a composition of standard functions
let process l =
l |> List.filter ((<>)1)
|> List.map ((+)1)
The OCaml standard library has had List.filter_map since 4.08. This can therefore now be written as:
List.filter_map (fun e -> if e <> 1 then Some (e + 1) else None)