How would you implement a beta-reduction function in F#? - f#

I am writing a lambda calculus in F#, but I am stuck on implementing the beta-reduction (substituting formal parameters with the actual parameters).
(lambda x.e)f
--> e[f/x]
example of usage:
(lambda n. n*2+3) 7
--> (n*2+3)[7/n]
--> 7*2+3
So I'd love to hear some suggestions in regards to how others might go about this. Any ideas would be greatly appreciated.
Thanks!

Assuming your representation of an expression looks like
type expression = App of expression * expression
| Lambda of ident * expression
(* ... *)
, you have a function subst (x:ident) (e1:expression) (e2:expression) : expression which replaces all free occurrences of x with e1 in e2, and you want normal order evaluation, your code should look something like this:
let rec eval exp =
match exp with
(* ... *)
| App (f, arg) -> match eval f with Lambda (x,e) -> eval (subst x arg e)
The subst function should work as follows:
For a function application it should call itself recursively on both subexpressions.
For lambdas it should call itself on the lambda's body expression unless the lambda's argument name is equal to the identifier you want to replace (in which case you can just leave the lambda be because the identifier can't appear freely anywhere inside it).
For a variable it should either return the variable unchanged or the replacement-expression depending on whether the variable's name is equal to the identifier.

Related

Is there a better way to write a commutative function in F#/OCaml?

Is there a more elegant or better way to write a commutative function in F#/OCaml rather than listing all possible cases?
let commutative x y =
match x,y with
a, _ -> val1
|_, a -> val1
|b, _ -> val2
|_, b -> val2
...
|_,z -> |valN
While I was writing the question I thought one could make the function recursive and swap the arguments if no match is found.
let rec commutative x y =
match x,y with
a,_ -> val1
|b,_ -> val2
...
|nox,noy -> commutative noy nox
But if I adopt this approach I cannot have in the function a default case that matches with everything unless I add another argument whose value indicates if it's the second time the function is being called and return the default value instead of calling the function with the swapped args if that's the case.
Any other ideas?
Does the language offer a construct for expressing the fact a function I'm defining is commutative?
(I'm answering for OCaml only as my F# is extremely rusty.)
There's no special help in OCaml for defining commutative functions.
If your parameter type has a reasonable ordering relation you can swap them if necessary to make x the larger (say). Almost all types can be compared in OCaml, so this should work very commonly. (Things that can't be compared: function types, cyclic values.)
I'm not sure this would help, but it might reduce the number of cases that you need to write out:
let commutative x y =
match (max x y, min x y) with
| A, _ -> value
. . .

OCaml functions passing in one less argument

I'm looking at solutions for a homework and the code implements an OCaml function that takes in two arguments but when its called, it's only passed one argument.
let rec func2 r x = match r with
| [] -> []
| (nt,rhs)::t -> if nt = x then rhs::(func2 t x) else func2 t x;;
let func1 r = fun x -> func2 r x;;
I would be calling func1 on a grammar rule like below by calling ( func1 awksub_rules )
let awksub_rules = [
Expr, [T"("; N Expr; T")"];
Expr, [N Num];
Num, [T"0"];
Num, [T"1"]
]
Expr and Num are just nonterminal types already defined and the T symbol means a terminal type.
I'm confused because func1 only takes in awksub_rules as an argument but the function declaration has two functions.
The intended output would be
function
| Expr -> [[T"("; N Expr; T")"]; [N Num]]
| Num -> [[T"0"]; [T"1"]]
I can see that func1 correctly returns a function and that func2 handles checking whether the left hand side (Expr or Num) is the same so it can concatenate to the list. But I have no idea what is passed into x.
When func1 is called with one argument, it returns another function, let's call it func3:
let func3 = func1 awksub_rules
At this point, there is no argument x yet. This new function still expects this argument to be passed in.
When you call this new function, you will pass in the value of x, and the computation will commence:
let result = func3 Num
I also would like to point out that func1 and func2 are logically equivalent because of the mechanism in ML called "partial application". That is, you can use func2 everywhere you use func1, and with same effect:
let func3 = func2 awksub_rules
let result = func3 Num
Fyodor Soikin's answer explains why func1 and func2 are logically the same. However, I don't want you to come away from this thinking that there is some magical language feature called "partial application". To stretch your mind, you need to understand how this arises from how functions work in OCaml.
In the ML languages, there is no such thing as a "function that takes in two arguments". Every function in ML takes exactly one argument (not zero, not two, not three; always one). The OCaml syntax
let rec func2 r x = ...
is syntactic sugar for
let rec func2 = function r -> function x -> ...
i.e. it is simply a definition of a function that returns another function. That's why the type of the function will be something like a -> b -> c (-> is right-associative, so that is the same as a -> (b -> c)) -- it says that it's a function that takes an a, and returns a function of type b -> c.
When you go to apply this function, what you think of as passing in two arguments, like func2 foo bar, is actually (because function application is left-associative) (func2 foo) bar, i.e. it is first applying func2 to the expression foo, and the result of that, a function, will then be applied to the expression bar.
The practice of taking in "multiple arguments" by taking in one argument and returning a function that takes another argument, etc. is called "currying". OCaml and other ML languages provide convenient syntax for defining curried functions (as you can see above, the common syntax let in OCaml allows you to define curried functions simply as listing the parameters next to each other), whereas in other languages, writing curried functions would require more verbose syntax. It's so convenient that, most of the time, we forget about it and think of it as multiple arguments. But it's always important to remember what it really means.
(Note that the OCaml compiler may or may not optimize curried functions into machine code functions that take multiple arguments, but that's an implementation detail that you shouldn't care about at the language level.)

f# signature matching explained

I am running into difficulty with F# in numerous scenarios. I believe I'm not grasping some fundamental concepts. I'm hoping someone can track my reasoning and figure out the (probably many) things I'm missing.
Say I'm using Xunit. What I'd like to do is, provided two lists, apply the Assert.Equal method pairwise. For instance:
Open Xunit
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 Assert.Equal test1 test2
The compiler complains that the function Equal does not take one parameter. As far as I can tell, shouldn't map2 be providing it 2 parameters?
As a sanity check, I use the following code in f# immediate:
let doequal = fun x y -> printf "result: %b\n" (x = y)
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 doequal test1 test2;;
This seems identical. doequal is a lambda taking two generic parameters and returning unit. List.map2 hands each argument pairwise into the lambda and I get exactly what I expected as output:
result: true
result: true
result: false
So what gives? Source shows Xunit.Equal has signature public static void Equal<T>(T expected, T actual). Why won't my parameters map right over the method signature?
EDIT ONE
I thought two variables x and y vs a tuple (x, y) could construct and deconstruct interchangeably. So I tried two options and got different results. It seems the second may be further along than the first.
List.map2 Assert.Equal(test1, test2)
The compiler now complains that 'Successive arguments should be separated spaces or tupled'
List.map2(Assert.Equal(test1, test2))
The compiler now complains that 'A unique overload method could not be determined... A type annotation may be needed'
I think that part of the problem comes from mixing methods (OO style) and functions (FP style).
FP style functions have multiple parameters separated by spaces.
OO style methods have parens and parameters separated by commas.
Methods in other .NET libraries are always called using "tuple" syntax (actually subtly different from tuples though) and a tuple is considered to be one parameter.
The F# compiler tries to handle both approaches, but needs some help occasionally.
One approach is to "wrap" the OO method with an FP function.
// wrap method call with function
let assertEqual x y = Assert.Equal(x,y)
// all FP-style functions
List.map2 assertEqual test1 test2
If you don't create a helper function, you will often need to convert multiple function parameters to one tuple when calling a method "inline" with a lambda:
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2
When you mix methods and functions in one line, you often get the "Successive arguments should be separated" error.
printfn "%s" "hello".ToUpper()
// Error: Successive arguments should be separated
// by spaces or tupled
That's telling you that the compiler is having problems and needs some help!
You can solve this with extra parens around the method call:
printfn "%s" ("hello".ToUpper()) // ok
Or sometimes, with a reverse pipe:
printfn "%s" <| "hello".ToUpper() // ok
The wrapping approach is often worth doing anyway so that you can swap the parameters to make it more suitable for partial application:
// wrap method call with function AND swap params
let contains searchFor (s:string) = s.Contains(searchFor)
// all FP-style functions
["a"; "b"; "c"]
|> List.filter (contains "a")
Note that in the last line I had to use parens to give precedence to contains "a" over List.filter
public static void Equal<T>(T expected, T actual)
doesn't take two parameters - it takes one parameter, which is a tuple with two elements: (T expected, T actual).
Try this instead:
List.map2 Assert.Equal(test1, test2)
It's all there in the type signatures.
The signature for Assert.Equals is something along the lines of 'a * 'a -> unit. List.map2 expects a 'a -> 'b -> 'c.
They just don't fit together.
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2 - works because the lambda wrapping Equals has the expected signature.
List.zip test1 test2 |> List.map Assert.Equal - works because you now have a single list of tuples, and since List.map wants an 'a -> 'b function (where 'a is now a tuple), Assert.Equal is now fair game.
It's simply not true that two values and a tuple are implicitly interchangeable. At least not as far as F# the language is concerned, or the underlying IL representation is concerned. You can think that it's that way when you call into F# code from, say, C# - an 'a -> 'b -> 'c function there is indeed called the same way syntactically as an 'a * 'b -> 'c function - but this is more of an exception than a rule.
According to its signature Xunit.Assert.Equal() takes a single 2 values tuple parameter

When executed will this be a tail call?

Once compiled and ran will this behave as a tail call?
let rec f accu = function
| [] -> accu
| h::t -> (h + accu) |> f <| t
Maybe there is an easy way to test behavior that I'm not aware of, but that might be another question.
I think this is much easier to see if you do not use the pipelining operator. In fact, the two pipelining operators are defined as inline, so the compiler will simplify the code to the following (and I think this version is also more readable and simpler to understand, so I would write this):
let rec f accu = function
| [] -> accu
| h::t -> f (h + accu) t
Now, you can read the definition of tail-call on Wikipedia, which says:
A tail call is a subroutine call that happens inside another procedure as its final action; it may produce a return value which is then immediately returned by the calling procedure.
So yes, the call to f on the last line is a tail-call.
If you wanted to analyze the original expression (h + accu) |> f <| t (without knowing that the pipelining operators are inlined), then this actually becomes ((h + accu) |> f) <| t. This means that the expression calls the <| operator with two arguments and returns the result - so the call to <| is a tail call.
The <| operator is defined like this:
let (<|) f a = f a
Now, the call to f inside the pipelining operator is also a tail-call (and similarly for the other pipelining operator).
In summary, if the compiler did not do inlining, you would have a sequence of three tail-calls (compiled using the .NET .tail instruction to make sure that .NET performs a tail-call). However, since the compiler performs inlining, it will see that you have a recursive tail-call (f calling f) and this can be more efficiently compiled into a loop. (But calls across multiple functions or operators cannot use loops that easily.)
If you look at the answer here, you will notice that f <| t is the same as f t (it only makes a difference if you put an expression in place of t which requires parenthesis).
Likewise x |> y is the same as y x.
This results in an equivalent expression which looks like this: f (h + accu) t, So (assuming the compiler doesn't have a bug or some such), your function should be tail recursive and most likely will be compiled down to a loop of some sort.

Issue with recursion writing a tiny parser in Haskell. Check variables

I'm still working on a tiny parser for a tiny language defined in a task at school. The parser that generates an AST(Abstract syntax tree) is working. What I want is to check the defined variables, they must be bounded by the let expression. First the method that is defined in the task(suggestion, not needed):
checkVars :: Expr -> Char
data Expr = Var Char | Tall Int | Sum Expr Expr | Mult Expr Expr | Neg Expr | Let Expr Expr Expr
deriving(Eq, Show)
A valid sentence would be "let X be 5 in *(2,X)". X would normally be a Var and 5 is normally an int. And the last can be any part of the dataExpr type. Main point: X is used somewhere in the last expression. The datatype for let is:
Let Expr Expr Expr
Link to the other questions I've asked about this task here just FYI;
First question
Second question
As you see the datatype to the checkVars is Expr, so here is an example of what I would feed to that function:
parseProg "let X be 4 in let Y be *(2 , X) in let Z be +(Y , X) in
+(+(X , Y) , Z)"
Let (Var 'X') (Tall 4) (Let (Var 'Y') (Mult (Tall 2) (Var 'X')) (Let
(Var 'Z') (Sum (Var 'Y') (Var 'X')) (Sum (Sum (Var 'X') (Var 'Y')) (Var
'Z'))))
Just 24
This is an all-inclusive example, the top part is the string/program being parsed. The second part, starting at line 3 (Let) is the AST, input for the checkVars function. And the bottom part "Just 24" is the evaluation. Which I will be back here for more help for.
Note: The point is to spit out the first unbound variable found as an error, and ' ' if everything is fine. Obviously if you want to do this another way you can.
Here's something to think about:
The first field of your Let constructor is an Expr. But can it actually hold anything else than Vars? If not, you should reflect this by making that field's type, say, String and adapting the parser correspondingly. This will make your task a lot easier.
The standard trick to evaluating an expression with let-bindings (which you are doing) is to write a function
type Env = [(String, Int)]
eval :: Expr -> Env -> Int
Note the extra argument for the environment. The environment keeps track of what variables are bound at any given moment to what values. Its position in the type means that you get to decide its value every time you call eval on child expressions. This is crucial! It also means you can have locally declared variables: binding a variable has no effect on its context, only on subexpressions.
Here are the special cases:
In a Var, you want to lookup the variable name in the environment and return the value that is bound to it. (Use the standard Prelude function lookup.)
In a Let, you want to add an extra (varname, value) to the front of the environment list before passing it on to the child expression.
I've left out some details, but this should be enough to get you going a long way. If you get stuck, ask another question. :-)
Oh, and I see you want to return a Maybe value to indicate failure. I suggest you first try without and use error to indicate unbound variables. When you have that version of eval working, adapt it to return Maybe values. The reason for this is that working with Maybe values makes the evaluation quite a bit more complicated.
I would actually try to evaluate the AST. Start by processing (and thus removing) all the Lets. Now, try to evaluate the resulting AST. If you run across a Var then there is an unbound variable.

Resources