I am very inexperienced in ML, and I just can't make sense of this.
Start question
Polymorphic Sorting
This function performing insertion sort on a list takes as arguments a comparison function less and a list l of elements to be sorted. The code compiles and runs correctly:
fun sort(less, nil) = nil |
sort(less, a : : l) =
let
fun insert(a, nil) = a : : nil |
insert(a, b : : l) = if less(a,b) then a : : (b: : l)
else b : : insert(a, l)
in
insert(a, sort(less, l))
end;
What is the type of this sort function? Explain briefly, including the type of the subsidiary function insert. You do not have to run the ML algorithm on this code; just explain why an ordinary ML programmer would expect the code to have this type. (End of question)
I've gotten the type of the sort function (by running the code in an SML interpreter), but I just can't get the second part about insert.
Type of sort function:
val sort = fn : ('a * 'a -> bool) * 'a list -> 'a list
Any help would be greatly appreciated.
That you figured out the type of sort by "cheating" makes the next step harder; don't take shortcuts.
(Nobody ever learned anything by peeking at the answer.)
But here's how you could figure out insert:
You know from
val sort = fn : ('a * 'a -> bool) * 'a list -> 'a list
that the second argument to sort is an 'a list.
In
insert(a, sort(less, l))
you can see immediately that it has some type (X * Y) -> Z for some X, Y, and Z.
You're passing the first element of sort's second argument - a - as insert's first argument.
Since sort's second argument is an 'a list, that list's first element is an 'a.
So X is 'a, and we now know that insert is ('a * Y) -> Z for some Y and Z.
The type of insert's second argument - sort(less, l) - is well known; it's 'a list.
So we now know that Y is 'a list, and insert is ('a * 'a list) -> Z for some Z.
All that remains is the return type, and since
insert(a, sort(less, l))
is what sort returns, it must have the same return type as sort.
So Z is 'a list.
In summary, insert's type is
('a * 'a list) -> 'a list
Related
I want to write a function f, that takes n arguments, where n is determined at runtime, and might vary at every call to the function, for example
let's say our function f takes an integer n which is the number of args, and n args of the same type and turns them into a list:
# f 3 'a' 'b' 'c';;
- : char list = ['a'; 'b'; 'c']
# f 2 1 2;;
- : int list = [1; 2]
I thaught of something like
let f acc n x =
if n = 0
then List.rev (x::acc)
else f [x] (x - 1)
but in this case it won't work because of the type difference.
Using currying, you can do something that resembles variadic functions, but you’ll have to convince the type checker. You will not be able to conveniently provide the arity of your function as a bare integer; instead, you can unary-encode the arity as a value of a GADT:
type (_, 'r) arity =
| O : ('r, 'r) arity
| I : ('f, 'r) arity -> (int->'f, 'r) arity
The encoding works as follows:
O : ('r, 'r) arity represents the arity of a “function that takes no argument” and returns an 'r;
I O : (int -> 'r, 'r) arity represents the arity of a function that takes an int and then returns an 'r;
I (I O) : (int -> int -> 'r, 'r) arity represents the arity of a function that takes two ints and then returns an 'r;
I (I (I O)) : (int -> int -> int -> 'r, 'r) arity is the arity of a function that takes three ints and then returns an 'r;
etc.
Instead of passing 3 as a first argument to your hypothetical variadic function, you would pass I (I (I O)). This value describes the sequence of arguments that the function is supposed to take (one int, then one int, then one int, then return). The function would then proceed recursively, destructing (inspecting) this description to decide what to do next You can implement your example function that builds the list of all its arguments, like so:
let rec f_aux : type f. int list -> (f, int list) arity -> f =
fun acc arity ->
begin match arity with
| O -> List.rev acc
| I a -> fun x -> f_aux (x :: acc) a
end
let f arity = f_aux [] arity
# f (C(C(C O))) ;;
- : int -> int -> int -> int list = <fun>
# f (C(C(C O))) 111 222 333 ;;
- : int list = [111; 222; 333]
As is common with GADTs, type inference is not enough and you have to annotate your definition with the intended type, including an explicit universal quantification (type f. … where f is the type variable being quantified).
The GADT defined above can only describe variadic functions that deal with ints, but notice that you can easily extend it to allow more types of arguments (then of course, you should adapt your variadic functions so that they deal with these added possibilities):
type (_, 'r) arity =
| O : ('r, 'r) arity
| I : ('f, 'r) arity -> (int->'f, 'r) arity
| B : ('f, 'r) arity -> (bool->'f, 'r) arity
| C : ('f, 'r) arity -> (char->'f, 'r) arity
| S : ('f, 'r) arity -> (string->'f, 'r) arity
(* etc. *)
let rec g_aux : type f. string -> (f, string) arity -> f =
fun acc arity ->
begin match arity with
| O -> acc
| I a -> fun x -> g_aux (acc ^ string_of_int x) a
| B a -> fun x -> g_aux (acc ^ if x then "true" else "false") a
| C a -> fun x -> g_aux (acc ^ String.make 1 x) a
| S a -> fun x -> g_aux (acc ^ x) a
(* etc. *)
end
let g arity = g_aux "" arity
# g (S(I(S(B(C O))))) ;;
- : string -> int -> string -> bool -> char -> string = <fun>
# g (S(I(S(B(C O))))) "Number " 42 " is prime. I swear, it’s " true '!' ;;
- : string = "Number 42 is prime. I swear, it’s true!"
As a matter of fact, this is essentially how pretty-printing is implemented in OCaml: when you write Printf.printf "%s%b" …, the format string is not actually a string, it is syntactic sugar kindly supplied by the compiler for a value of some very complicated GADT type such as (_,_,_,_,_,_) format6 (6 type parameters!). You might just as well build the GADT value by hand (don’t). This syntactic sugar is the only magic that the compiler does for pretty-printing, everything else works with standard language features.
Well, we have a system that works, at least it typechecks. Syntax is not pretty unless the compiler gives you sugar. More importantly, arities are encoded and checked within the static type system, which means, they are known at compile-time. You cannot (or at least it’s hard to do safely) read an arity as input of your program, dynamically, at run-time.
The actual question is: why would you actually need to do that, instead of just using a list? It brings nothing except syntactic convenience perhaps.
Your requirement doesn't make sense, since there is no way to dynamically change the number of parameters of a function at runtime. The number of parameters in any function call is directly visible by examining the text of the source code:
f a b (* Two parameters *)
f a b c (* Three parameters *)
There is no dynamic evaluation mechanism in OCaml (like the eval mechanism of other languages). This is part of what it means to be statically typed.
You can get the effect you want just by passing a list to the function.
What's a good way to convert List (Maybe a) to Maybe (List a) in Elm?
The logic is simple:
return Just (List a) if all items are Just a
otherwise, return Nothing.
Example 1:
input: [ Just 1, Just 2, Just 3 ]
output: Just [ 1, 2, 3 ]
Example 2:
input: [ Just 1, Nothing, Just 3 ]
output: Nothing
Can it be done easily with some of the built-in functions?
The best I came up with looks like this:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
List.foldl
(\maybeItem ->
\maybeResultList ->
case ( maybeItem, maybeResultList ) of
( Just item, Just resultList ) ->
Just (List.append resultList [ item ])
( _, _ ) ->
Nothing
)
(Just [])
listOfMaybes
And what would be an appropriate name for this kind of function? As I was searching for an answer, I saw that there's a function called sequence in Haskell which seems to be doing something similar.
You can use the Elm Fancy Search tool and search on the function signature: List (Maybe a) -> Maybe (List a)
The first result turns up Maybe.Extra.combine
#Chad Gilbert's answer sure is correct, but if you're looking for a simpler implementation of such a function, then the following line will do the trick:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
List.foldr (Maybe.map2 (::)) (Just []) listOfMaybes
Or just:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList = List.foldr (Maybe.map2 (::)) (Just [])
Maybe.map2 just takes a function and two Maybe values and applies the function to the values:
> Maybe.map2 (+) (Just 2) (Just 3)
Just 5 : Maybe.Maybe number
> Maybe.map2 (::) (Just 2) (Just [1])
Just [2,1] : Maybe.Maybe (List number)
Note, that (::) function (prepend to the list) is used instead of (++) or List.append because it's more performant for the lists. Then foldr must be used instead of foldl to retain the order.
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
I'm looking for a functional data structure that supports the following operations:
Append, O(1)
In order iteration, O(n)
A normal functional linked list only supports O(n) append, while I could use a normal LL and then reverse it, the reverse operation would be O(n) also which (partially) negates the O(1) cons operation.
You can use John Hughes's constant-time append lists, which seem nowadays to be called DList. The representation is a function from lists to lists: the empty list is the identity function; append is composition, and singleton is cons (partially applied). In this representation every enumeration will cost you n allocations, so that may not be so good.
The alternative is to make the same algebra as a data structure:
type 'a seq = Empty | Single of 'a | Append of 'a seq * 'a seq
Enumeration is a tree walk, which will either cost some stack space or will require some kind of zipper representation. Here's a tree walk that converts to list but uses stack space:
let to_list t =
let rec walk t xs = match t with
| Empty -> xs
| Single x -> x :: xs
| Append (t1, t2) -> walk t1 (walk t2 xs) in
walk t []
Here's the same, but using constant stack space:
let to_list' t =
let rec walk lefts t xs = match t with
| Empty -> finish lefts xs
| Single x -> finish lefts (x :: xs)
| Append (t1, t2) -> walk (t1 :: lefts) t2 xs
and finish lefts xs = match lefts with
| [] -> xs
| t::ts -> walk ts t xs in
walk [] t []
You can write a fold function that visits the same elements but doesn't actually reify the list; just replace cons and nil with something more general:
val fold : ('a * 'b -> 'b) -> 'b -> 'a seq -> 'b
let fold f z t =
let rec walk lefts t xs = match t with
| Empty -> finish lefts xs
| Single x -> finish lefts (f (x, xs))
| Append (t1, t2) -> walk (t1 :: lefts) t2 xs
and finish lefts xs = match lefts with
| [] -> xs
| t::ts -> walk ts t xs in
walk [] t z
That's your linear-time, constant-stack enumeration. Have fun!
I believe you can just use standard functional linked list:
To append element, you can use cons (which is O(1))
To iterate elements in the order in which they were inserted, you can first reverse the list,
(which is O(N)) and then traverse it, which is also O(N) (and 2xO(N) is still just O(N)).
How about a difference list?
type 'a DList = DList of ('a list -> 'a list)
module DList =
let append (DList f) (DList g) = (DList (f << g))
let cons x (DList f) = (DList (fun l -> x::(f l)))
let snoc (DList f) x = (DList (fun l -> f(x::l)))
let empty = DList id
let ofList = List.fold snoc empty
let toList (DList f) = f []
You could create a functional Deque, which provides O(1) adding to either end, and O(N) for iteration in either direction. Eric Lippert wrote about an interesting version of an immutable Deque on his blog note that if you look around you will find the other parts of the series, but that is the explanation of the final product. Note also that with a bit of tweaking it can be modified to utilize F# discriminated unions and pattern matching (although that is up to you).
Another interesting property of this version, O(1) peek, removal, and add, from either end (i.e. dequeueLeft, dequeueRight, dequeueLeft, dequeueRight, etc. is still O(N), versus O(N*N) with a double list method).
What about a circularly-linked list? It supports O(1) appends and O(n) iteration.
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.