Is there a way to express the function application operator/function with Hana? - c++

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.

Related

Using a particular higher-order helper function to compute factorial

I'm taking a MOOC (no credit). One of the assigned problems is to write a factorial function using a function that follows this:
(’a->’a)->(’a->bool)->’a->’a
I've created that function:
fun do_until (f, g) = fn x => case g(f x) of
false => f x
| _ => do_until(f,g) (f x);
but I've had difficulty using my do_until function to implement factorial.
The solution should follow this format I believe:
fun factorial x = (do_until (f, g)) x
The problem I see is that the 'g' function can only validate the result, and if validated, then return that result. Since the function type descriptors are fairly restrictive, it limits you from passing in a tuple to g, then verifying off part of the tuple and returning the other part. ie. (factorial, int to mult) then g would verify from #2 and return #1. Unfortunately the types prevent that. I'm starting to think using do_until as a helper function is impossible unless you compute the factorial some other way and then 'g' would just compare your result to that. Please let me know if I'm wrong and where to go next!
You have the wrong type – the function should be curried – and you will probably have more luck if you give the parameters more descriptive names than "f" and "g":
fun do_until next done x = if done x
then x
else do_until next done (next x)
Note that you can pass anything from factorial to do_until – for instance a tuple that holds your computation state – and then "take it apart" once do_until is done. (I suspect that this is why you're stuck.)

Getting the opposite boolean output of anonymous functions [SML]

Part of a solution, I'm trying to figure a way in order to convert the value of a boolean anonymous function to its opposite. for example I have function f which is as following: fn x => x > 8. I would like some operator like not which will convert the output to be the opposite, so the anonymous will actually calculate fn x => x <= 8. Something like as following:
fun foo f x = not f x;
But it won't work because not works only on boolean values. I know that I can do it as following:
fun foo f x = if f x then false else true;
But, I want to somehow do it in one line without any ifs. Is it possible?
There is already not which can be composed with a predicate, e.g. like:
val isntSpace = not o Char.isSpace
In OCaml's Base library there is a function Fn.non that does this:
fun non f x = not (f x)
It seems that you were only a set of parentheses away from this.
This would let you write:
val isntSpace = non Char.isSpace

Dealing with unit in Ocaml

So I have a function r which is supposed to apply a function to every element in the list provided it meets a given predicate, and return that list. i.e.
let p x = x > 2;;
let f x = x+1;;
r p f [1;2] => []
I am using a map function that applies a function to every element in a list and then returns that list. Thus my implementation for r is as follows
let r f p l = map f (map (fun x -> if (p x) then x) l );;
but if I attempt to call r like in the example above I get a type error because f and p are expressions for ints and it expected expression for units. Where did I go wrong?
First of all let me explain, why unit comes into play.
In OCaml if/then/else is not a statement, it is an expression, like ternary operator in C-like languages or like conditional expression in Python. Than means, that being an expression it always must have a value. You cannot just give an expression for the true branch, and omit the else branch, unless the value to the else branch is trivial and always known to a compiler. And the latter is only possible for the unit type. Since this type is inhabited with only one value, then if you true branch returns a value of type unit, compiler already knows what would return the false branch. That's why you can omit else part of the expression, that evaluates to unit. And the omission of the else part is satisfactory proof for the compiler that the whole expression has type unit. That means, that in expression if (p x) then x, compiler decided that x has type unit, because there is no else part.
Now to the task. map must return a value for each element of the list. It cannot skip or rearrange, or change the structure. For this there're other higher order functions called filter_map, concat_map, filter, etc.
But lets try to do something without leaving the original wording. So back to your example, we need do something in the else part. What we should return to designate that there is no value? We can return None that is a value of type option, e.g.,
if p x then Some x else None
Notice, that we also need to lift the then part to the option type. As a result we will have a list of type 'a option list. Then we need to filter it, removing Nones.
Other choice is to return an empty list (aka nil), instead of None:
if p x then [x] else []
Then we will have a 'a list list that can be easily transformed to 'a list with concat operation. Moreover, we can notice, that there is no need to create an intermediate list, we can apply f just in place (i.e., there is an opportunity for deforesting optimization here):
if p x then [f x] else []
And finally we have:
let r f p l = concat (map (fun x -> if p x then [f x] else []) l)
Later, you will discover, that both option and list are monads, and this trick with map and concat is actually the core operation for all monads, called bind and denoted as >>=. With this operator defined, we can write r function more elegantly:
let r f p l = l >>= fun x -> if p x then [f x] else []
where the bind operator can be implemented (inefficiently), as
let (>>=) x f = concat (map f x)
But this all was functional mumbo-jumbo, practically, it is better just to use fold_left (as Jeffrey suggested), and accumulate your result in an auxiliary list, without forgetting to reverse it:
let r f p l = rev (fold_left (fun xs x -> if p x then f x :: xs else xs) [] l)
And in real-world programming, you will be using the standard library functions such as List.filter_map or List.concat_map for that.
The map function applies a function to every element of a list and returns the list of results. It always returns a list of equal length to the input list. So your problem statement doesn't make complete sense.
At a lower level, the expression if (p x) then x is only legitimate if x has type unit. I.e., the meaning of if b then e is the same as if b then e else (), and both sides of the if have to be the same type.
If you want to return a list of a different length than your input list, you'll need to use a fold function rather than map.

How SML achieve abstraction? [closed]

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).

subtract functions with type real in ml

I'm trying to subtract two functions(both with type real) in moscow ml. It then says "Overloaded - cannot be applied to arguments of type real -> real. So how should I write the function?
fun CircleArea x = x*x*Math.pi
fun SquareArea x:real = 4*x*x
fun Area x = SquareArea - CircleArea
You probably don't actually want to subtract one function from another, but the return values of those functions once they are applied. You could achieve this in the following way:
fun Area x = (SquareArea x) - (CircleArea x)
The parentheses are not mandatory, since function application (i.e. the space between SquareArea and x) binds tighter than any binary operator, including -.
You should consider using the following naming convention in ML: Regular functions have a lowercase starting symbol, while value constructors for algebraic types have uppercase starting symbols. For example:
fun area x = squareArea x - circleArea x
But:
datatype shape = Square of int * int
| Circle of int
Subtraction of functions like we have in mathematics isn't provided as a built-in operator. You can, however, define your own.
Mathematically speaking, we define
(f - g)(x) = f(x) - g(x)
We can replicate this definition in SML as follows:
infix 5 --
fun f -- g = fn x => f x - g x
What this does is produce an operator, --, such that f -- g produces the function corresponding to fn x => f x - g x, i.e. the function that given an x calculates f x - g x.
Note, due to the type-ambiguity in the - operator, it'll default to let you subtract 'a -> int functions. In your case you'll want to subtract 'a -> real functions, so you'll need a slight modification:
infix 5 --
fun f -- g = fn x => f x - g x : real
If you use this ---operator, you will be able to define your Area function like so:
val area = squareArea -- circleArea;
(I took the liberty of making the first letter of function names lowercase, to match the SML naming conventions.)