Getting the opposite boolean output of anonymous functions [SML] - 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

Related

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

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.

Why am I getting "unbound variable or constructor" in my SML program

I have written a method to return the first element in a list that satisfies a function (passed in via currying). The function returns NONE or SOME depending on whether or not the element satisfies a condition. I'm using Pattern Matching
However, I'm getting the dreaded error:
Error: unbound variable or constructor: my_function
I'm new to SML and one of the hardest things I find is understanding the error messages. From previous experience with the message, I would think the problem is that my_function never returns, but I'm having trouble seeing the logic problem here. Can someone take a quick look and tell me the problem? Is the problem that I'm raising an error when there is no element that satisfies the input function f?
I'm interested in what's wrong and perhaps more importantly, is there any way to get more information when you see this sort of error?
val my_function = fn f => fn lst => (* Notice currying *)
case lst of
[] => raise NoAnswer (* Get here is nothing in lst saf
| x::xs => case f(x) of NONE => ( my_function f xs)
| SOME y => x
val test = my_function(fn x => if x < 3 then SOME x else NONE) [1,2,3,4] = 2
Thanks, Dave
If you declare a function with the val keyword, the function can't be defined recursively. Hence, the problem is here:
... NONE => ( my_function f xs) ...
You can say that you want the function to be defined recursively by adding the rec keyword to the declaration.
val rec my_function = fn f => fn list => ...
Alternatively, the fun keyword is syntactic sugar for val rec. fun also includes nice syntactic sugar for currying:
fun my_function f lst = (* This is equivalent to your first line *)
Sometimes you still want to use just the val keyword and not val rec. For instance,
val f = fn x => x + 3
val f = fn y => f y + 4 (* f here refers to the previous declaration of f *)

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

Finding max element in a list in SML

I am trying to find the the greatest value in a list using Standard ML. I need to use the given fold function:
fun fold f [] base = base
| fold f (x::xs) base = fold f xs (f x base);
Here is what i have so far:
fun max (x::xs) = fold (fn (a, b) => if a > b then a else 0) x (x::xs);
I have 0 in there because if the list is empty then I need to return 0;
This is only part of another function that I need to define, but I'm struggling with the fold part.
In your definition of the fold function, you require that the function f must take it's arguments in curry form, that is: f 1 1 instead of f(1,1).
As I understand, then your definition of the fold function is the right one. Thus you need to make proper changes to the anonymous function in the max function.
In SML, currying is actually just syntactic sugar. For example:
fun foo a b = a+b
would end up as (after desugaring):
val rec foo = fn a => fn b => a+b
It is also seen that the two functions has the same type:
- fun foo a b = a+b;
val foo = fn : int -> int -> int
- val rec foo = fn a => fn b => a+b;
val foo = fn : int -> int -> int
Thus the anonymous function must be define somewhat along the same lines.
Also you have mixed the arguments to fold. In the last part of the max function, you are giving the two last arguments in the reverse order.
The last problem is that your anonymous function returns 0. This screws with the invariant of you anonymous function and makes it fail in some cases. For example:
max [1,4,65,7,6];
Try to figure out why yourself.
If you really need to return 0 if the input list to max is empty, then you should pattern match that case. This also fixes the warning about "match nonexhaustive", and is the correct place to do it.
fun max [] = 0
| max (x::xs) = fold (fn a => fn b => if a > b then a else b) (x::xs) x;

How can I avoid warnings when I apply function to a known list of arguments in OCaml?

How can I transform several values a,b,c etc. to a',b',c' etc, such that x'=f(x)? The values are bound to specific names and their quantity is known at compile-time.
I tried to apply a function to a list in the following way:
let [a';b'] = List.map f [a;b] in ...
But it yields warning:
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
[]
Any way to avoid it?
You can write a few functions for mapping on to uniform tuples, i.e.:
let map4 f (x,y,z,w) = (f x, f y, f z, f w)
let map3 f (x,y,z) = (f x, f y, f z)
let map2 f (x,y) = (f x, f y)
and then you can just use them whenever the need arises.
let (x',y') = map2 f (x,y)
Unfortunately not. You can silence the compiler by writing
match List.map f [a;b] with
[a';b'] -> ...
| _ -> assert false
but that's all.
The compiler is trying to help you here. It tells you that you are trying to assign an unknown list to [a';b'] . What if one year later you change this code so that the first list, [a;b], is refactored to a different place in the code so you don't see it, and the function f is changed so that it sometimes returns a different list? You will then sometimes get a run-time exception trying to match [a';b'] with a wrong list. The compiler cannot check that the code is correct, hence the warning.
Why not write
let (a', b', c') = ( f a, f b, f c);;
It's not so much more work to write this, but completely safe against any future changes in the code.