I'm doing an academic exercise (for personal growth). I want to find programming languages that allow you to define functions that are capable of accepting themselves (i.e., pointers to themselves) as arguments.
For example, in JavaScript:
function foo(x, y) {
if (y === 0) return;
x(x, y - 1);
}
foo(foo, 10);
The code above will execute foo() exactly 11 times before y reaches zero, causing the recursion to terminate.
I tried defining a similar function in OCaml like this:
let rec foo x y = if y < 1 then "hi" else x x (y - 1);;
But it failed with a type error:
Error: This expression has type 'a -> 'b -> 'c
but an expression was expected of type 'a
The type variable 'a occurs inside 'a -> 'b -> 'c
I'm wondering, is it possible to define such a function in OCaml? I'm particularly interested in OCaml because I know it has a global type inference system. I want to know if such functions are compatible with global type inference. Thus, I'm looking for examples of these types of functions in any language with global type inference.
It is possible in any language, that features either mutability or recursion or both, to call a function with a pointer to itself. Basically, all conventional Turing complete languages, have those features, therefore there are so many answers.
The real question is how to type such functions. Non strongly typed languages (like C/C++) or dynamically (or gradually) typed are of no interest, as they enable type coercing of some form, that basically makes the task trivial. They rely on a programmer to provide a type and take it as granted. Therefore, we should be interested in strictly typed languages with the static type system.
If we will focus on OCaml, then your definition could be accepted by the compiler if you pass the -rectypes option, which will disable the occurrence check, that disallows recursive types. Indeed, the type of your function is ('a -> int -> string as 'a) -> int -> string,
# let foo x y = if y < 1 then "hi" else x x (y - 1);;
val foo : ('a -> int -> string as 'a) -> int -> string = <fun>
Note that, you don't need rec here, as your function is not really recursive. What is recursive is the type, ('a -> int -> string as 'a), here as expands to the left up to the parenthesis, i.e., 'a = 'a -> int -> string. This is a recurrence and, by default, many compilers disallow such equations (i.e., equations where the same type variable occurs on both sides of the equation, hence the name occurrence check). If this check is disabled, the compiler will allow this and alike definitions. However, it was observed that the occurrence check catches more bugs than disallows well-formed programs. In other words, when the occurrence check is triggered it is more likely a bug, rather than a deliberate attempt to write a well-typed function.
Therefore, in real life, programmers feel reluctant to introduce this option to their build systems. The good news is that if we will massage the original definition a little bit, we don't really need recursive types. For example, we can change the definition to the following,
let foo x y = if y < 1 then "hi" else x (y - 1)
which now has type
val foo : (int -> string) -> int -> string = <fun>
I.e., it is a function that takes another function of type (int -> string) and returns a function of type (int -> string). Therefore, to run foo we need to pass it a function that recursively calls foo, e.g.
let rec run y = foo run y
This is where the recursion comes into play. Yes, we didn't pass the function to itself directly. Instead, we passed it a function, that references foo and when foo calls this function it, in fact, calls itself, via an extra reference. We may also notice, that wrapping our function in a value of some other kind1) (using, record, or variant, or object) will also allow your definition. We can even specify those extra helper type as [##unboxed] so that the compiler will not introduce extra boxing around the wrapper. But this is a sort of cheating. We still won't be passing the function to itself, but an object that contains this function (even though the compiler optimization will remove this extra indirection, from the perspective of the type system, those are still different objects, therefore the occurrence check is not triggered). So, we still need some indirection, if we don't want to enable recursive types. And let's stick to the simplest form of indirection, the run function and try to generalize this approach.
In fact, our run function is a specific case of a more general fixed-point combinator. We can parametrize run with any function of type ('a -> 'b) -> ('a -> 'b), so that it will work not only for foo:
let rec run foo y = foo (run foo) y
and in fact let's name it fix,
let rec fix f n = f (fix f) n
which has type
val fix : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
And, we can still apply it to our foo
# fix foo 10
The Oleg Kiselyov web site is an excellent resource that shows many ways of defining the fixed point combinator in OCaml, Scheme, and Haskell.
1) This is essentially the same as the delegate approach, that was shown in other answers (both including languages with type inference like Haskell and OCaml, and languages that don't, like C++ and C#).
Your OCaml function requires a recursive type, i.e., a type that contains a direct reference to itself. You can define such types (and have values of such types) if you specify -rectypes when you run OCaml.
Here's a session with your function:
$ rlwrap ocaml -rectypes
OCaml version 4.06.1
# let rec foo x y = if y < 1 then "hi" else x x (y - 1);;
val foo : ('a -> int -> string as 'a) -> int -> string = <fun>
# foo foo 10;;
- : string = "hi"
#
The default is not to support recursive types, because they almost always are the result of programming errors.
As Jeffrey points out, OCaml can deal with this, if you activate -rectypes. And the reason that it is not turned on by default is not that it's a problem for ML-style type inference, but that it's usually not helpful to programmers (masks programming errors).
Even without the -rectypes mode you can easily construct an equivalent functions via an auxiliary type definition. For example:
type 'a rf = {f : 'a rf -> 'a}
let rec foo x y = if y < 1 then "hi" else x.f x (y - 1)
Note that this still infers everything else, such as the other function arguments. Sample use:
foo {f = foo} 11
Edit: As far as ML type inference is concerned, the only difference between the algorithm with and without -rectypes is that the latter omits the occurs-check during unification. That is, with -rectypes the inference algorithm actually becomes "simpler" in a sense. Of course, that assumes a suitable representation of types as graphs (rational trees) that allows cycles.
Some examples I can write:
C++
C
C#
Python
Scheme
C++
Ok, so not the first language you would think of, and definitely not a painless way of doing it, but it's very much possible. It's C++ and it's here because they say write about what you know :) Oh, and I wouldn't recommend doing this outside of academic interest.
#include <any>
#include <iostream>
void foo(std::any x, int y)
{
std::cout << y << std::endl;
if (y == 0)
return;
// one line, like in your example
//std::any_cast<void (*) (std::any, int)>(x)(x, y - 1);
// or, more readable:
auto f = std::any_cast<void (*) (std::any, int)>(x);
f(x, y - 1);
}
int main()
{
foo(foo, 10);
}
If the casts are too much (and too ugly) you can write a small wrapper like bellow. But the biggest advantage is performance: you completely bypass the std::any heavy type.
#include <iostream>
class Self_proxy
{
using Foo_t = void(Self_proxy, int);
Foo_t* foo;
public:
constexpr Self_proxy(Foo_t* f) : foo{f} {}
constexpr auto operator()(Self_proxy x, int y) const
{
return foo(x, y);
}
};
void foo(Self_proxy x, int y)
{
std::cout << y << std::endl;
if (y == 0)
return;
x(x, y - 1);
}
int main()
{
foo(foo, 10);
}
And a generic version of the wrapper (forwarding omitted for brevity):
#include <iostream>
template <class R, class... Args>
class Self_proxy
{
using Foo_t = R(Self_proxy<R, Args...>, Args...);
Foo_t* foo;
public:
constexpr Self_proxy(Foo_t* f) : foo{f} {}
constexpr auto operator()(Self_proxy x, Args... args) const
{
return foo(x, args...);
}
};
void foo(Self_proxy<void, int> x, int y)
{
std::cout << y << std::endl;
if (y == 0)
return;
x(x, y - 1);
}
int main()
{
foo(foo, 10);
}
C
You can do this in C also:
https://ideone.com/E1LkUW
#include <stdio.h>
typedef void(* dummy_f_type)(void);
void foo(dummy_f_type x, int y)
{
printf("%d\n", y);
if (y == 0)
return;
void (* f) (dummy_f_type, int) = (void (*) (dummy_f_type, int)) x;
f(x, y - 1);
}
int main()
{
foo((dummy_f_type)foo, 10);
}
The trap to avoid here is that you cannot use void* as the type for x as it's not valid to cast a pointer type to a data pointer type.
Or, as shown by leushenko in the comments, you can use the same pattern with a wrapper:
#include <stdio.h>
struct RF {
void (* f) (struct RF, int);
};
void foo(struct RF x, int y)
{
printf("%d\n", y);
if (y == 0)
return;
x.f(x, y - 1);
}
int main()
{
foo((struct RF) { foo }, 10);
}
C #
https://dotnetfiddle.net/XyDagc
using System;
public class Program
{
public delegate void MyDelegate (MyDelegate x, int y);
public static void Foo(MyDelegate x, int y)
{
Console.WriteLine(y);
if (y == 0)
return;
x(x, y - 1);
}
public static void Main()
{
Foo(Foo, 10);
}
}
Python
https://repl.it/repls/DearGoldenPresses
def f(x, y):
print(y)
if y == 0:
return
x(x, y - 1)
f(f, 10)
Scheme
And finally here's a functional language
https://repl.it/repls/PunyProbableKernelmode
(define (f x y)
(print y)
(if (not (= y 0)) (x x (- y 1)))
)
(f f 10)
One language that is incredible for recursion/iteration (the name for what you're asking for) is a dialect of Lisp called Scheme. Check out a book called SICP for this language. Calling self is a technique to implement anonymous recursion.
Here is what your procedure would look like in Scheme:
(define (foo x y)
(if (= y 0) null (x x (- y 1))))
(foo foo 10)
For completeness, Haskell.
newtype U a = U { app :: U a -> a }
foo :: Int -> ()
foo y = f (U f) y
where
f x y | y <= 0 = ()
| otherwise = app x x (y-1)
Trying:
> foo 10
()
The statically typed languages seem to be doing more or less the same thing to achieve this: put the function into a record and pass that to itself as an argument. Haskell's newtype creates ephemeral "records" though, so it really is the function itself, at run time.
The dynamically typed languages just pass self to self and are done with it.
You can do it in C which supports function pointers, C# which supports delegates, and Java in which you might need to declare your own #FunctionalInterface for the method to match.
Related
My question
I'm referring to a function which does essentially the following (modulo const, &, perfect forwarding, or whatever is appropriate):
auto constexpr dollar = [](auto f, auto x){ return f(x); }; // Why calling it "dollar"? Keep reading...
Is such a function expressable only via Boost.Hana?
Why did I think of it?
In Haskell, such a function exists, and it's called ($) ($ in infix form), and its definition is the following (source code)
($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b
f $ x = f x
and you could write the second line simply as either of the following
(f $) = f
($) f = f
where the second form makes it apparent that ($) is essentially the same as the id (identity function)
id :: a -> a
id x = x
just with a signature that enforces that the first argument be of function type a -> b and the second argument of type a.
Indeed, applying f to x in Haskell can be done also by writing this
f `id` x
i.e. using `id` instead of $.¹
How is that related to Hana?
Since Hana does offer an id function, I was wondering if that (maybe together with something else) can be used to define a function application utility without manually writing the lambda at the top of this post.
The difficult part
The hard part here is that when you write f `id` x in Haskell, there's not much really a point in arguing on whether you're passing 1 or 2 arguments to id, because all functions are curried by default.
That's not true in C++. For instance I can do this:
#include <boost/hana/functional/id.hpp>
#include <iostream>
using boost::hana::id;
int main() {
auto plus1 = [](int x){ return x + 1; };
std::cout << id(plus1)(3) << std::endl; // prints 4
}
which looks a lot like id is curried and is being given two inputs one after the other rather than together, but that's not true. It's just that id(plus1) is returning plus1, which is fed with 3. I don't know how to get the following (which would be equivalent to plus1 `id` 3 or id plus1 3 in Haskell) work:
std::cout << id(plus1, 3) << std::endl; // doesn't even compile obviously
The true origin of the puzzle
After reading To Mock a Mockingbird, I wondered: "How do I implement the Thrush in C++ only with Boost.Hana?" (And the Thrush is the boost::hana::flipped version of the function application operator.)
¹In reality it's not exactly the same if want to write chains of applications, as the two operators have different associativity, so f $ g $ x == f `id` (g `id` x), but this is not relevant to the question, I believe.
I know this could be stupid question, but since I'm new to Ocaml, please give me some tips on defining functions with specific type.
I want to define function which type has int * int * (int -> int) -> int
So I made a function like this.
let rec sigma a b func:int->int=
if a >= b then func(a)
else func(a) + sigma(a+1, b, func)
But sigma function here does not have type int * int * (int->int) -> int. Instead its type is int->int->(int->int)->int.
How should I define function sigma to have type int * int * (int->int) -> int?
(Error Message :
Error: This expression has type 'a * 'b * 'c
but an expression was expected of type int
The type int * int * (int->int) -> int denotes a function that takes a 3-tuple and returns and integer. A tuple (pair, triple, quadruple, etc) is written as (a,b,c,...), e.g.,
let rec sigma (a,b,func) : int =
if a >= b then func(a)
else func(a) + sigma(a+1, b, func)
With all that said, it is usually a bad idea to pass arguments via tuples in OCaml. It hampers currying, inefficient (each tuple is boxed into a separate value), and in general non-functional and not nice.
Also, when you constrain a parameter of a function, you shall parenthesize it, e.g., (func : int -> int).
And normally functions in OCaml are applied by juxtaposition of a function name and its arguments, e.g., given a function add
let add x y = x + y
we can apply (call it) just as add 3 5 (not add(3,5)!)
Therefore, the conventional way to define your sigma function would be
let rec sigma a b func : int =
if a >= b then func a
else func a + sigma (a+1) b func
signature MAPPABLE = sig
type 'a mappable
val fmap : ('a -> 'b) -> 'a mappable -> 'b mappable
end
structure Option : MAPPABLE = struct
type 'a mappable = 'a option
fun fmap f v =
case v of
(SOME x) => SOME (f x)
| NONE => NONE;
end
structure List : MAPPABLE = struct
type 'a mappable = 'a list
fun fmap f v = map f v
end
fun incByFive x = x + 5
Really just to have a function that does stuff with fmap
fun mapToPair f x =
let val b = List.fmap f x
in (b,b)
end
val lst = mapToPair incByFive [1,2,3];
Suppose you want to make a generic implementation, that works for
all instances of MAPPABLE. The following does not work
fun mapToPair f x =
let val b = MAPPABLE.fmap f x
in (b,b)
end
It seems, that SML people point to Functors, if that needs to be done.
I tried implementing one, for a generic implementation of mapToPair
functor FMAPFUNCTOR (structure Q : MAPPABLE)
= struct
fun mapToPair f x =
let val b = Q.fmap f x
in (b,b)
end
end;
However, to use it with what in Haskell I'd call a functor
instance, I need to instantiate the functor (this reminds me of C++
templates for some reason)
structure MAPPABLE_TO_PAIR = FMAPFUNCTOR (structure Q = List);
val lstByPoly = MAPPABLE_TO_PAIR.mapToPair incByFive [1,2,3]
I would have to repeat that instantiation for every MAPPABLE
instance I want to use. I guess Haskell performs something like this,
too. Just implicitly.
Now I wonder if there is any shortcut / sugar for a better "user
experience" in SML that I have missed. Because really, it seems kind
of a lot of boilerplate in the way in order to use this in a code
base.
I guess Haskell performs something like this, too. Just implicitly.
The Haskell standard library defines and imports a ton of type class instances. Given a sufficient set of ML functors, their applications and their implicit compile-time imports, you could achieve something quite convenient.
But Haskell does let you automate type class instance declarations in ways that SML doesn't.
For example, instance Foo t => Bar t where ... is comparable to SML's higher-order functors, but in SML you explicitly have to generate a module that corresponds to Bar t for each concrete Foo t. Haskell also lets you derive instances syntactically.
OCaml had modular implicits from 2014 (example), but they mainly give you syntax sugar to refer to defined functor instances, rather than generate them.
I suspect that the reason ML module systems are still more explicit than Haskell's is because of things like overlapping instances.
Andreas Rossberg contributed 1ML in 2014 in which modules are first-class citizens. That means a function could take a module as an argument, e.g. like this:
;; Higher-kinded polymorphism
type MONAD (m : type => type) =
{
return 'a : a -> m a;
bind 'a 'b : m a -> (a -> m b) -> m b;
};
map 'a 'b (m : type => type) (M : MONAD m) (f : a -> b) mx =
M.bind mx (fun x => M.return (f x));
do map :
'a => 'b => (m : type => type) => (M : MONAD m) => (a -> b) -> m a -> m b;
This is still research-y in the sense that the compiler has "TOY" in its name, but it'd be an example of an ML (although not Standard ML) that does something comparably generic with modules.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am new in SML and it is my first time to learn a functional language. I suppose there is abstraction of SML. I have not found perfect explanation of how to achieve abstraction in SML. Does anyone can offer a explanation?
Generally speaking, there are at least two forms of "abstraction" in programming:
Abstracting the client (parameterisation)
Abstracting the implementation (encapsulation)
(If you care, these correspond to universal and existential quantification in logic and type theory.)
In ML, parameterisation can be done on two levels. Either in the small, using functions (abstraction over values) and polymorphism (abstraction over types). Note in particular that functions are first-class, so you can parameterise one function over another. For example:
fun map f [] = []
| map f (x::xs) = f x :: map f xs
abstracts list transformation over the transforming function f as well as the element types.
In the large, parameterisation can be done using the module system: a functor abstracts a whole module over another module (i.e., over both values and types). For example, you could also write the map function as a functor:
functor Mapper(type t; type u; val f : t -> u) =
struct
fun map [] = []
| map (x::xs) = f x :: map xs
end
But usually you use functors for mass abstraction, i.e., in cases where there is more than just a single function you need to parameterise.
Encapsulation is also achieved by using modules. Specifically, by sealing them, i.e., hiding details of their types behind a signature. For example, here is a (naive) implementation of integer sets:
signature INT_SET =
sig
type set
val empty : set
val add : int * set -> set
val mem : int * set -> bool
end
structure IntSet :> INT_SET = (* ':>' hides the implementation of type set *)
struct
type set = int list
val empty = []
fun add(x, s) = x::s
fun mem(x, s) = List.exists (fn y => y = x) s
end
Outside the structure IntSet, its type set is fully abstract, i.e., it cannot be interchanged with lists. That is the purpose of the so-called sealing operator :> for modules.
Both forms of abstraction can occur together. For example, in ML one would usually implement a set as a functor:
signature ORD =
sig
type t
val compare : t * t -> order
end
signature SET =
sig
type elem
type set
val empty : set
val add : elem * set -> set
val mem : elem * set -> bool
end
functor Set(Elem : ORD) :> SET where type elem = Elem.t =
struct
type elem = Elem.t
datatype set = Empty | Branch of set * elem * set
val empty = Empty
fun add(x, Empty) = Branch(Empty, x, Empty)
| add(x, Branch(l, y, r)) =
case Elem.compare(x, y) of
LESS => Branch(add(x, l), y, r)
| EQUAL => Branch(l, y, r)
| GREATER => Branch(l, y, add(x, r))
fun mem(x, Empty) = false
| mem(x, Branch(l, y, r)) =
case Elem.compare(x, y) of
LESS => mem(x, l)
| EQUAL => true
| GREATER => mem(x, r)
end
This implementation of sets works for any type for which an ordering function can be provided. Unlike the naive implementation before, it also uses a more efficient search tree as its implementation. However, that is not observable outside, because the type's implementation is again hidden.
SML programs frequently are build on a descriptive types for the problem at hand. The language then uses pattern matching to figure out what case your are working with.
datatype Shape = Circle of real | Rectangle of real*real | Square of real
val a = Circle(0.2)
val b = Square(1.3)
val c = Rectangle(4.0,2.0)
fun area (Circle(r)) = 3.14 * r * r
| area (Square(s)) = s * s
| area (Rectangle(b,h)) = b * h
Does this help to explain a little about sml?
In SML you can define "abstractions" by means of using a combination of things like algebraic data types and signatures.
Algebraic data types let you define new types specific to the problem domain and signatures let you provide functionality/behavior around those types and provide a convenient way to implement information hiding and extensibility and reusability.
Combining this things you can create "abstractions" whose implementation details are hidden from you and that you simply understand through their public interfaces (whatever the signature expose).
fun curry f x y = f (x, y);
fun uncurry f (x, y) = f x y;
fun compose (f, g) x = f (g x);
I understand compose function, but not quite understand curry and uncurry in ML. Can anyone explain these?
Also, what do the following two lines mean?
(1) compose (compose, uncurry compose)
(2) compose (uncurry compose, compose)
If you look at the types, then you will clearly see what curry and uncurry does.
Remember that it is possible to define function which either takes its arguments as one big tuple, or as multiple arguments (in reality it becomes a "chain" of functions each taking 1 argument, see this wiki):
fun foo (a,x) = a*x+10
fun bar a x = a*x+20
The difference is clearly seen in their types:
val foo = fn : int * int -> int
val bar = fn : int -> int -> int
The curry function "transforms" a function that takes its arguments as a tuple, into a "chain" of functions that each takes 1 of the arguments. This is specifically handy when we want to compose a series of functions where some of them have been partially applied with arguments. See how the type of foo is changed:
- curry foo;
val it = fn : int -> int -> int
Now we can try and compose the two functions:
- (curry foo 5 o bar 1) 4;
val it = 130 : int
First 4 is applied to bar 1 as the argument x, then the result of that computation (bar 1 4) is given as the x argument to foo.
Obviously uncurry is used for the reverse process:
- uncurry bar;
val it = fn : int * int -> int