I'm using an implementation of lazy lists where the type can be either Nil or Cons (value, thunk), where thunk is a function from unit to the rest of the list.
I'm trying to write a function cross, which would function as List.combine does. Unfortunately, I'm having syntax errors.
open Sequence;;
let rec (cross : 'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t) = match seq1 with
Nil -> match seq2 with
Cons (value2, thunk2) -> Cons ((Nil, value2), function () -> (cross Nil (thunk2 ())))
| Cons (value1, thunk1) -> match seq2 with
Nil -> Cons ((value1, Nil), function() -> (cross Nil (thunk1 ())))
| Cons (value2, thunk2) -> Cons ((value1, value2), function() -> (cross (thunk1 ()) (thunk2 ())))
This produces the error:
Error: Unbound value seq1
what am I doing wrong?
UPDATE:
This type checks, but is not of the type I'm looking for.
let rec cross (seq1 : 'a Sequence.t) (seq2 : 'b Sequence.t) : ('a * 'b) Sequence.t = match seq1 with
Nil -> match seq2 with
Cons (value2, thunk2) -> Cons ((Nil, value2), function () -> (cross Nil (thunk2 ())))
| Cons (value1, thunk1) -> match seq2 with
Nil -> Cons ((value1, Nil), function() -> (cross Nil (thunk1 ())))
| Cons (value2, thunk2) -> Cons ((value1, value2), function() -> (cross (thunk1 ()) (thunk2 ())))
val cross :
'a Sequence.t Sequence.t ->
'a Sequence.t Sequence.t -> ('a Sequence.t * 'a Sequence.t) Sequence.t =
<fun>
This is not the type of cross that I want. I'm looking for:
'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t
you are going to kick yourself... where is seq1 defined?
let rec (cross : 'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t) =
You define the type of cross, but you don't bind the variables to anything (I guess, you can say that).
let rec cross (seq1:'a Sequence.t) (seq2:'a Sequence.t) :('a * 'b) Sequence.t =
EDIT:
I think your matching is well, mis-matched. Use begin ... end blocks around the cases, I think what is happening (and since I don't have Sequence, I cannot verify) is that the match cases you intend for the outer match are being applied to the inner one, matching seq2. for example,
match x with
| 0 -> match y with
| 1 -> "x:0, y:1"
| 2 -> match y with
| 0 -> "y:0, x:2"
Although, spatially, it looks fine, the second match, match y with is bound with the | 2 -> ... match case. Here is a version with the being ... end keywords surrounding the match cases. The second begin ... end isn't needed, but it's probably a good idea to do it anyway for clarity.
match x with
| 0 -> begin match y with
| 1 -> "x:0, y:1" end
| 2 -> begin match y with
| 0 -> "y:0, x:2" end
in the first line, you're trying to match against seq1, but this value is unbound meaning that it's nowhere to be found.
That's exactly the same as :
# let t =
match t1 with
_ -> ();;
Error: Unbound value t1
You have to name your arguments.
For your updated question, the reason the types are 'a Sequence.t Sequence.t is because of the line
Cons ((Nil, value2), ...)
Recall that Nil is a sequence itself, so by putting that there it forces all the elements of the input sequences to be sequences too.
This error occurs when you have mentioned a name which has not been defined (technically “bound to a
value”). This might happen if you have mistyped the name.
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.
I'm writing a macro expansion algorithm for a programming project, and I am attempting to add an r7rs-small compliant macro expansion pass. One part of this expansion algorithm requires matching patterns.
However, I'm having difficulty coming up with a pattern-matching algorithm that deals with Scheme's repetition patterns. The given example is from the r7rs small spec, which expands let* into nested lets:
(define-syntax let*
(syntax-rules ()
((let* () body1 body2 ...)
(let () body1 body2 ...)
((let* ((name1 val1) (name2 val2) ....)
body1 body2 ...)
(let ((name1 val1))
(let* ((name2 val2) ...)
body1 body2 ...)))))
As you can see, the p ... syntax needs to be able to repeatedly match 0 or more repetitions of the pattern p.
My first attempt was:
-- This datatype is a given
data SExp = SAtom String | SPair SExp SExp | SEmpty
data Pat = PatEmpty -- ()
| PatPair Pat Pat -- (p1 . p2)
| PatWild -- _
| PatVar String -- x
| PatRepeated Pat -- p ...
| PatAtom String -- a
type MatchResult = Map String SExp
matchPat :: Pat -> SExp -> Maybe MatchResult
matchPat p e =
case (p, e) of
(PatEmpty, SEmpty) -> Just Map.empty
(PatWild, _) -> Just Map.empty
(PatVar x, _) -> Just (Map.singleton x e)
(PatAtom a, SAtom a') | a == a' -> Just Map.empty
(PatPair p1 p2, SPair e1 e2) -> do
-- This is the problem case
-- This implementation cannot handle repetitions,
-- since p1 should be able to consume parts of e2
res1 <- matchPat p1 e1
res2 <- matchPat p2 e2
Just (Map.union res1 res2)
_ -> Nothing
However, I'm skeptical that this pattern representation is good enough for implementing this kind of matching algorithm. Any help would be great.
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
I've just come across the following code snippet in OCaml's documentation about GADTs:
let rec eval : type a. a term -> a = function
| Int n -> n
| Add -> (fun x y -> x + y)
| App (f, x) -> (eval f) (eval x)
which, once evaluated in utop, has the following signature:
val eval : 'a term -> 'a = <fun>
I also noticed that, when replacing type a. a term -> a by 'a term -> 'a or just removing the signature, the function doesn't compile anymore.
...
| Add -> (fun x y -> x + y)
...
Error: This pattern matches values of type (int -> int -> int) term
but a pattern was expected which matches values of type int term
Type int -> int -> int is not compatible with type int
So what is this notation? What makes it different of 'a t ?
Is it specific to GADTs?
The manual explains the syntax a few sections up: http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc80
In short, type a. ... means that the locally abstract type a must be polymorphic.
I am looking for a haskell function or pattern that is a sort of "foldWhile" except instead of folding over a list it uses a functions output..some code will probably explain it better.
Simplified and pseudo:
nums :: [Integer]
nums = [1]
cond :: v -> [Integer] -> Bool
cond v ls = elem v ls
func :: x -> ls -> [Integer]
func x ls = x `some_op` ls
And I need a pattern of application like:
(cond 1 num) && func x num -> num'
(cond 1 num') && func x num' -> num''
(cond 1 num'') && func x num'' -> num'''
...
Once cond returns False, yield the last num.
Any help would be appreciated, thanks in advance.
I think you want a combination of iterate and takeWhile:
iterate :: (a -> a) -> a -> [a]
takeWhile (a -> Bool) -> [a] -> [a]
iterateWhile :: (a -> a) -> (a -> Bool) -> a -> [a]
iterateWhile func cond = takeWhile cond . iterate func
And in your case you'd want to use it as
lastWhere :: (a -> a) -> (a -> Bool) -> a -> a
lastWhere func cond = last . iterateWhile func cond
main = do
let x = lastWhere (+1) (<10) 1
print x
-- prints "9"
You can probably do this with a fold, but why bother when you have this solution already? If evaluating the condition is separate from generating the values, then separate those two concerns, rather than trying to tie them together. This is what iterateWhile does. Since it's lazily evaluated, this only generates values until it finds one that doesn't meet the condition, and it only needs a single loop to do so.
Since iterateWhile produces a list of elements all satisfying that condition, you can then simply take the last element. If you need the first element that fails, I would do
firstWhere :: (a -> a) -> (a -> Bool) -> a -> a
firstWhere func cond = head . dropWhile cond . iterate func