I am trying to define a function wrapper that curries a tuple in SML.
fun curry f = fn (x, y) z => f x y z;
Gives me the error
Non-identifier applied to a pattern.
I am new to ML and not sure why the pattern matching in fn doesn't work.
How could I make this work?
I am trying to define a function wrapper that curries a tuple in SML.
fun curry f = fn (x, y) z => f x y z;
How could I make this work?
Closures in SML don't allow for multiple arguments, but you can nest them instead.
What curry usually does is take a function f that normally accepts a tuple (x, y) and instead returns a modified function that takes x and y separately. Here is a number of equivalent ways to define curry:
fun curry f x y = f (x, y)
fun curry f x = fn y => f (x, y)
fun curry f = fn x => fn y => f (x, y)
val curry = fn f => fn x => fn y => f (x, y)
Its opposite, uncurry instead takes a function f that takes x and y separately and returns a modified function that takes (x, y). Here is one way to write uncurry:
fun uncurry f (x, y) = f x y
It's easy to mix up the two.
One way to fix the function you've written so that it compiles is insert an extra => fn:
fun what_is_this f = fn (x, y) => fn z => f x y z
(* ^- there *)
Before giving it a name, let's analyse what it does. It has the type signature:
fn : ('a -> 'b -> 'c -> 'd) -> 'a * 'b -> 'c -> 'd
(* now a tuple -^ ^- still curried *)
meaning that it takes a function of three curried arguments (x, y and z) and returns a modified function where the first two arguments are now in a tuple (uncurried) and the third is still curried. This is really a less generic version of uncurry. A more clear way of writing it would be:
fun what_is_this f (x, y) z = f x y z
If you use uncurry on a function of three arguments, you get the same effect, but you can't use what_is_this on anything with two curried arguments. So I'd say that this is a less useful variant of uncurry.
There are however other more useful variants of curry/uncurry. For example, you could make an uncurry_twice that converts f x y z into (uncurry_twice f) ((x, y), z), or an uncurry3 that converts f x y z into (uncurry3 f) (x, y, z):
fun uncurry_twice f = uncurry (uncurry f)
fun uncurry3 f (x, y, z) = f x y z
Related
I´m trying to learn more about dependent types using IDRIS.
The example I am trying to emulate uses composition of Vectors.
I understand Functor and Applicative implementations for Vectors but I am struggling to implement them for the Composition.
data Vector : Nat -> Type -> Type where
Nil : Vector Z a
(::) : a -> Vector n a -> Vector (S n) a
Functor (Vector n) where
map f [] = []
map f (x::xs) = f x :: map f xs
Applicative (Vector n) where
pure = replicate _
fs <*> vs = zipWith apply fs vs
Now the Composition and Decomposition-Function look like this:
data (:++) : (b -> c) -> (a -> b) -> a -> Type where
Comp : (f . g) x -> (f :++ g) x
unComp : (f :++ g) a -> (f . g) a
unComp (Comp a) = a
User with Vectors it encapsulates a Vector of Vectors.
Now I need an Applicative for the Composition (Vector n) :++ (Vector n).
I can´t even get Functor to work and am mainly trying to see what I´m doing wrong. I tried the following and, since Functor is already implemented for Vectors, that this would work
Functor ((Vector n) :++ (Vector n)) where
map f (Comp []) = Comp []
map f (Comp (x::xs)) = Comp ((f x) :: (map f (Comp xs)))
but the Compiler gives an Error-Message:
When checking an application of constructor Main.:::
Unifying a and Vector (S n) a would lead to infinite value
Isn´t unifying and element of type a and a Vector n a exactly the purpose of (::)?
I am obviously doing something wrong and I can´t get this to work. I also have the feeling it´s probably easy to solve, but after hours of reading and trying I still don´t get it.
If someone could give me advice or explain to me how the Functor and Applicative implementations could look like, I would be very grateful.
Update: Idris 2 now has this builtin. Functor for Compose, Applicative for Compose
I think you can implement a general instance of Functor and Applicative like with Haskell's Compose.
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
a <$ (Compose x) = Compose (fmap (a <$) x)
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose (liftA2 (<*>) f x)
liftA2 f (Compose x) (Compose y) =
Compose (liftA2 (liftA2 f) x y)
To answer your specific question (but don't do it this way):
Functor ((Vector n) :++ (Vector n)) where
map f (Comp x) = Comp $ map (map f) x
The Y combinator (from the wikipedia article) is defined as:
Y = \f.(\x.f(x x)) (\x.f(x x))
so when we call Y on g:
Y g = (\f.(\x.f(x x)) (\x.f(x x))) g
= (\x.g(x x)) (\x.g(x x))
= g((\x.g(x x)) (\x.g(x x)))
= g (Y g)
The repetition results in this:
Y g = g(Y g) = g(g(Y g)) = g(...g(Y g)...)
Because this expansion is over a unary function, I can't tell if this is a left fold or a right fold.
My understanding of a left fold is that it resembles this (with a binary function f):
f (f (f (f 1 2) 3) 4) 5)
Whereas a right fold over binary function f looks like this:
f 1 (f 2 (f 3 (f 4 5)))
I would imagine that any unary function, however, would look the same as a left-fold or right-fold expansion:
f (f (f (f (f x))))
Is this correct? If not, does the Y combinator expand into a left-fold or a right-fold?
Fixed point combinators like Y merely enable anonymous recursion. What you do with this recursion is totally up to you. You can define both a left associative fold and a right associative fold with it. I hope you don't mind me illustrating this in Javascript:
// simplified Y combinator with eta abstraction due to eager evaluation
const fix = f => x => f(fix(f)) (x);
// left fold
const foldl = fix(rec => f => acc => ([x, ...xs]) =>
x === undefined
? acc
: rec(f) (f(acc) (x)) (xs));
// right fold
const foldr = fix(rec => f => acc => ([x, ...xs]) =>
x === undefined
? acc
: f(x) (rec(f) (acc) (xs)));
console.log(
foldl(x => y => x - y) (0) ([1,2,3])); // -6
console.log(
foldr(x => y => x - y) (0) ([1,2,3])); // 2
I wonder if there is a way to do something like this (x, y < 0, z)
with y < 0
There are three cases in my example y = 0, y < 0 and else.
I know how to implement this function with different approaches, but
I just like this way and want to know if this is possible in some way.
let rec f = function
| (x, 0, y) -> x
| (x, y < 0, z) -> f (x y z)
| (x, y, z) -> f (z y x)
Just that you know, I removed the complexity of the tuple in the recursive call, so the function has no purpose right now.
You can add a condition after a pattern using the when keyword. With that, you can do what you want like this:
let rec f = function
| (x, 0, y) -> x
| (x, y, z) when y < 0 -> f (x, y, z)
| (x, y, z) -> f (z, y, x)
This will cause infinite recursion because f (x, y, z) doesn't change anything about the arguments, but I assume that problem does not exist in your real code.
How do you make an anonymous recursive function (something simple for example factorial n?) I have heard it is possible but no idea how to make it work in OCaml.
let a =
fun x -> ....
I just don't know how to keep it going...
Here is a definition of factorial using only anonymous functions:
let fact =
(fun f -> (fun x a -> f (x x) a) (fun x a -> f (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1))
It requires the use of the -rectypes flag.
Here's a session showing that it works:
$ rlwrap ocaml -rectypes
OCaml version 4.03.0
let fact =
(fun f -> (fun x a -> f (x x) a) (fun x a -> f (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1));;
val fact : int -> int = <fun>
# fact 8;;
- : int = 40320
I cheated somewhat by looking up the Y Combinator here: Rosetta Code: Y Combinator
Update
Disclaimer: you would do better to read up on lambda calculus, fixed points, and the Y Combinator than to get your info from me. I'm not a theorist, just a humble practitioner.
Following the actual computation is almost impossible (but definitely worth doing I'm sure). But at a high level the ideas are like this.
The first line of the definition is the Y Combinator, which in general calculates the fixed point of a function. It so happens that a recursive function is the fixed point of a function from functions to functions.
So the first goal is to find the function whose fixed point is the factorial function. That's the second line of the definition. If you give it a function of type int -> int, it gives you back another function of type int -> int. And if you give it the factorial function, it gives you back the factorial function. This means that the factorial function is its fixed point.
So then when you apply the Y Combinator to this function, you do indeed get the factorial function.
Let me try to expand a bit on Jeffrey Scofield's answer. A non-anonymous recursive definition of the factorial function could be
let rec fact n =
if n < 2 then 1 else n * fact (n - 1)
The first problem you encounter when you try to define an anonymous recursive function is how to do the actual recursive call (fact (n - 1) in our case). For a call we need a name and we do not have a name for an anonymous function. The solution is to use a temporary name. With the temporary name f, the definition body is just
fun n -> if n < 2 then 1 else n * f (n - 1)
This term does not have a type, because the "temporary name" f is unbound. But we can turn it into a value that does have a type by bounding f as well. Let us call the result g:
let g = fun f n -> if n < 2 then 1 else n * f (n - 1)
g is not yet anonymous at the moment, but only because I want to refer to it again.
Observe that g has type (int -> int) -> (int -> int). What we want (the factorial function) will have type (int -> int). So g takes something of the type we want (a function type in this case) and produces something of the same type. The intuition is that g takes an approximation of the factorial function, namely a function f which works for all n up to some limit N and returns a better approximation, namely a function that works for all n up to N+1.
Finally we need something that turns g into an actual recursive definition.
Doing so is a very generic task. Recall that g improves the approximation quality. The final factorial function fact is one which cannot be further improved. So applying g to fact should be the same as just fact. (Actually that is only true from a value point of view. The actual computation inherent in g fact n for some n is different from that of just fact n. But the returned values are the same.) In other words, fact is a fixed point of g. So what we need is something that computes fixed points.
Luckily, there is a single function that does so: The Y combinator. From a value point of view, the Y combinator (let us use y in OCaml, as uppercase is reserved for constructors) is defined by the fact that y g = g (y g) for all g: given some function g, the combinator returns one of its fixed points.
Consequently,
y : (`a -> `a) -> `a
In our case the type variable is instantiated by (int -> int).
One possible way to define y would be
let y = fun g -> (fun x -> g (x x)) (fun x -> g (x x))
but this works only with lazy evaluation (as, I believe, Haskell has). As OCaml has eager evaluation, it produces a stack overflow when used. The reason is that OCaml tries to turn something like y g 8 into
g (y g) 8
g (g (y g)) 8
g (g (g (y g))) 8
...
without ever getting to call g.
The solution is to use deferred computation inside of y:
let y = fun g -> (fun x a -> g (x x) a) (fun x a -> g (x x) a)
One drawback is that y does not work for arbitrary types any more. It only works for function types.
y : ((`b -> `c) -> (`b -> `c)) -> (`b -> `c)
But you asked for recursive definitions of functions anyway, not for recursive definitions of other values. So, our definition of the factorial function is y g with y and g defined as above. Neither y nor g are anonymous yet, but that can be remedied easily:
(fun g -> (fun x a -> g (x x) a) (fun x a -> g (x x) a))
(fun f n -> if n < 2 then 1 else n * f (n - 1))
UPDATE:
Defining y only works with the -rectypes option. The reason is that we apply x to itself.
There is also an "intuitive" way to accomplish anonymous recursion without resorting to Y combinators.
It makes use of a let binding to store the value of a lambda that accepts itself as an argument, so that it can call itself with itself as the first parameter, like so:
let fact = (let fact0 = (fun self n -> if n < 2 then 1 else n * self self (n - 1)) in (fun n -> fact0 fact0 n));;
It's anonymous only to the extent that it is not defined with let rec.
I have a university course about functional programming, where I use SML. As a preparation for the exam, I am working on some of the older exam sets without solutions.
One of the only questions I really have problems with is the following question using foldl:
Consider the program skeleton: fun
addGt k xs = List.foldl (...) ... xs;
Fill in the two missing pieces
(represented by the dots ...), so that
addGt k xs is the sum of those
elements in xs, which are greater than
k. For example, addGt 4 [1, 5, 2, 7,
4, 8] = 5 + 7 + 8 = 20
I am sure this is really easy, but I have a very hard time understanding the foldl and foldr functions.
What I have now is the following (which seems to be very wrong if you ask my compiler!):
fun addGt(k,xs) = List.foldl ( fn x => if x > k then op+ else 0) 0 xs;
I would really appreciate some help with this question, and maybe a very short comment which would cast some light on the foldl and foldr functions!
A solution that I just though of is the following:
fun addGt(k, xs) = List.foldl (fn (x, y) => if x >= 5 then x + y else y) 0 xs;
But let me explain. First of all check the type of the List.foldl function, it's:
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
So List.foldl is a curried function that takes as first parameter another function of type ('a * 'b -> 'b). You used (fn x => if x > k then op+ else 0) which has type int -> int. You should instead provide List.foldl with a function that takes a tuple of type int * int and returns an int, so something like this: (fn (x, y) => do stuff). That's why your code didn't compile, you passed a wrong type of function in foldl.
Now you can think of foldl this way:
foldl f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_n, f(x_(n - 1), ..., f(x2, f(x1, b)) ...)) where f is a function of type ('a * 'b -> 'b), b is something of type 'b and the list [x_1, x_2, ..., x_(n - 1), x_n] is of type 'a list.
And similar for foldr you can think it in this way:
foldr f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_1, f(x_2, ..., f(x_(n - 1), f(x_ n, b))
If you call foldl f s ls on a list, ls = [x1, x2, ..., xn], then you get the result:
f(xn, ... f(x2, f(x1, s)))
That is, it starts by finding
a1 = f(x1, s)
Then
a2 = f(x2, a1)
and so on, until it's through the list.
When it's done, it returns an.
You can think of the a-values as being a sort of accumulator, that is, ai is the result as it would be if the list was only [x1, x2, ..., xi] (or rather, the first i elements of the list).
Your function will usually have the form:
fn (x, a) => ...
What you then need to do is think: Okay, if I have the next element in the list, x(i+1), and the value ai, which is the result for the list [x1, x2, ..., xi], what do I need to do to find the value a(i+1), which is the result for the list [x1, x2, ..., xi, x(i+1)].
s can be thought of as the value given to the empty list.
foldr works the same way, only you start from the back of the list instead of from the front.