I'm exploring "advanced" uses of OCaml functions and I'm wondering how I can write a function with variable number of arguments.
For example, a function like:
let sum x1,x2,x3,.....,xn = x1+x2,+x3....+xn
With a bit of type hackery, sure:
let sum f = f 0
let arg x acc g = g (acc + x)
let z a = a
And the (ab)usage:
# sum z;;
- : int = 0
# sum (arg 1) z;;
- : int = 1
# sum (arg 1) (arg 2) (arg 3) z;;
- : int = 6
Neat, huh? But don't use this - it's a hack.
For an explanation, see this page (in terms of SML, but the idea is the same).
OCaml is strongly typed, and many techniques used in other (untyped) languages are inapplicable. In my opinion (after 50 years of programming) this is a very good thing, not a problem.
The clearest way to handle a variable number of arguments of the same type is to pass a list:
# let sum l = List.fold_left (+) 0 l;;
val sum : int list -> int = <fun>
# sum [1;2;3;4;5;6];;
- : int = 21
Related
I have to write a function sum that takes as first argument a value n. The second argument is a function f so that sum calculates the Gaussian sum.
In a second step, I have to implement thesum_gauss (int->int) using sum and a lambda expression.
This is my idea for the function sum:
let rec sum (n:int) (f:int->int) : int =
if n < 1 then 0
else sum (n-1) f + f n
And this is sum_gauss which throws an error:
let sum_gauss = sum ((i:int) -> fun (i:int) : int -> i)
The error is:
Line 1, characters 30-32:
Error: Syntax error: ')' expected
Line 1, characters 22-23:
This '(' might be unmatched
I don't understand why this error is raised because every left bracket is matched by a right bracket.
Rewriting with type inference cleaning things up:
let rec sum n f =
if n < 1 then 0
else sum (n-1) f + f n
If you wish to add all number from 1 to n. you need to pass the number and the function to sum_gauss as separate arguments.
let sum_gauss n = sum n (fun x -> x)
Of course, fun x -> x is really just Fun.id.
let sum_gauss n = sum n Fun.id
If you feel like being extra clever and you're already using the Fun module you can use Fun.flip to pass Fun.id as the second argument of sum and elide n from the definition entirely. The fact that sum is not polymorphic avoids weak typing issues with partial application.
let gauss_sum = Fun.(flip sum id)
I am working on the following exercise:
Define a function libDiv which computes the list of natural divisors of some positive integer.
First define libDivInf, such that libDivInf n i is the list of divisors of n which are lesser than or equal to i
libDivInf : int -> int -> int list
For example:
(liDivInf 20 4) = [4;2;1]
(liDivInf 7 5) = [1]
(liDivInf 4 4) = [4;2;1]
Here's is my attempt:
let liDivInf : int -> int -> int list = function
(n,i) -> if i = 0 then [] (*ERROR LINE*)
else
if (n mod i) = 0 (* if n is dividable by i *)
then
i::liDivInf n(i-1)
else
liDivInf n(i-1);;
let liDiv : int -> int list = function
n -> liDivInf n n;;
I get:
ERROR: this pattern matches values of type 'a * 'b ,but a pattern
was expected which matches values of type int
What does this error mean? How can I fix it?
You've stated that the signature of liDivInf needs to be int -> int -> int list. This is a function which takes two curried arguments and returns a list, but then bound that to a function which accepts a single tuple with two ints. And then you've recursively called it in the curried fashion. This is leading to your type error.
The function keyword can only introduce a function which takes a single argument. It is primarily useful when you need to pattern-match on that single argument. The fun keyboard can have multiple arguments specified, but does not allow for pattern-matching the same way.
It is possible to write a function without using either.
let foo = function x -> x + 1
Can just be:
let foo x = x + 1
Similarly:
let foo = function x -> function y -> x + y
Can be written:
let foo x y = x + y
You've also defined a recursive function, but not included the rec keyword. It seems you're looking for something much more like the following slightly modified version of your attempt.
let rec liDivInf n i =
if i = 0 then
[]
else if (n mod i) = 0 then
i::liDivInf n (i-1)
else
liDivInf n (i-1)
I'm trying to make program which counts the number of odd digits in integer using Haskell. I have ran into problem with checking longer integers. My program looks like this at the moment:
oddDigits:: Integer -> Int
x = 0
oddDigits i
| i `elem` [1,3,5,7,9] = x + 1
| otherwise = x + 0
If my integer is for example 22334455 my program should return value 4, because there are 4 odd digits in that integer. How can I check all numbers in that integer? Currently it only checks first digit and returns 1 or 0. I'm still pretty new to haskell.
You can first convert the integer 22334455 to a list "22334455". Then find all the elements satisfying the requirement.
import Data.List(intersect)
oddDigits = length . (`intersect` "13579") . show
In order to solve such problems, you typically split this up into smaller problems. A typical pipeline would be:
split the number in a list of digits;
filter the digits that are odd; and
count the length of the resulting list.
You thus can here implement/use helper functions. For example we can generate a list of digits with:
digits' :: Integral i => i -> [i]
digits' 0 = []
digits' n = r : digits' q
where (q, r) = quotRem n 10
Here the digits will be produced in reverse order, but since that does not influences the number of digits, that is not a problem. I leave the other helper functions as an exercise.
Here's an efficient way to do that:
oddDigits :: Integer -> Int
oddDigits = go 0
where
go :: Int -> Integer -> Int
go s 0 = s
go s n = s `seq` go (s + fromInteger r `mod` 2) q
where (q, r) = n `quotRem` 10
This is tail-recursive, doesn't accumulate thunks, and doesn't build unnecessary lists or other structures that will need to be garbage collected. It also handles negative numbers correctly.
I'm completely lost on this. It was explained that functions are right justified so that let add x y = x + y;; has a function type of int -> int -> int or int -> (int -> int).
I'm not sure how I'd define a function of type (int -> int) -> int. I was thinking I'd have the first argument be a function that passes in an int and returns an int. I've tried:
let add = fun x y -> x + y --- int -> int -> int
let add = fun f x = (f x) + 3 --- ('a -> int) -> 'a -> int
What about
let eval (f: int -> int) :int = f 0
?
fun x -> (x 1) + 1;;
- : (int -> int) -> int = <fun>
or
let foo f = (f 1) + 1;;
val foo : (int -> int) -> int = <fun>
it works like
foo (fun x -> x + 1);;
- : int = 3
Your questions is highly associated with the notion of Currying.
But before that, let me say that if you want to write a function that needs a parameter to be a function, you could declare a normal function, and just use its parameter like a function. No need to complicate it. See the ex:
let f x = x(10) + 10
Now comes the currying part. In OCaml, the parameters are semantically evaluated just one at a time, and after evaluating an argument, an anonymous function is returned. This is important because it lets you supply part of the arguments of a function, creating effectively a new function (which is called Partial Application).
In the example bellow, I use + as a function (parenthesis around an operator turn it to a normal function), to create an increment function. And apply it to the previous f function.
let incr = (+) 1
f incr
The code evaluates to f incr = incr(10) + 10 = 21
This link has more information on the topic applied to OCaml.
I have a function in F# , like:
let MyFunction x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y
Basically, MyFunction takes an input x and returns y. However, in the process of calculation, there are a few working variables (intermediate variables), and due to the nature of my work (civil engineering), I need to report all intermediate results. How should I store all working variables of the function ?
I'm not exactly sure what kind of "report" your are expecting. Is this a log of intermediate values ? How long time this log should be kept ? etc. etc This is my attempt from what I understand. It is not ideal solution because it allows to report values of intermediate steps but without knowing exactly which expression has generated the intermediate value (I think that you would like to know that a value n was an output of workingVariable1 = x + 1 expression).
So my solution is based on Computation Expressions. Computation expression are a kind of F# "monads".
First you need to define a computation expression :
type LoggingBuilder() =
let log p = printfn "intermediate result %A" p
member this.Bind(x, f) =
log x
f x
member this.Return(x) =
x
Next we create an instance of computation expression builder :
let logIntermediate = new LoggingBuilder()
Now you can rewrite your original function like this:
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = x + 1
let! workingVariable2 = workingVariable1 + 1
let! y = workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
If you run loggedWorkflow function passing in 10 you get this result :
> loggedWorkflow 10;;
intermediate result 11
intermediate result 12
intermediate result 13
val it : int * int * int = (13, 11, 12)
As I said your intermediate values are logged, however you're not sure which line of code is responsible for.
We could however enchance a little bit to get the FullName of the type with a corresponding line of code. We have to change a little our computation expression builder :
member this.Bind(x, f) =
log x (f.GetType().FullName)
f x
and a log function to :
let log p f = printfn "intermediate result %A %A" p f
If you run again loggedWorkflow function passing in 10 you get this result (this is from my script run in FSI) :
intermediate result 11 "FSI_0003+loggedWorkflow#34"
intermediate result 12 "FSI_0003+loggedWorkflow#35-1"
intermediate result 13 "FSI_0003+loggedWorkflow#36-2"
This is a hack but we get some extra information about where the expressions like workingVariable1 = x + 1 were definied (in my case it is "FSI_") and on which line of code (#34, #35-1). If your code changes and this is very likely to happen, your intermediate result if logged for a long time will be false. Note that I have not tested it outside of FSI and don't know if lines of code are included in every case.
I'm not sure if we can get an expression name (like workingVariable1 = x + 1) to log from computation expression. I think it's not possible.
Note: Instead of log function you coud define some other function that persist this intermediate steps in a durable storage or whatever.
UPDATE
I've tried to came up with a different solution and it is not very easy. However I might have hit a compromise. Let me explain. You can't get a name of value is bound to inside a computation expression. So we are not able to log for example for expression workingVariable1 = x + 1 that "'workingVariable1' result is 2". Let say we pass into our computation expression an extra name of intermediate result like that :
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = "wk1" ## x + 1
let! workingVariable2 = "wk2" ## workingVariable1 + 1
let! y = "y" ## workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
As you can see before ## sign we give the name of the intermediate result so let! workingVariable1 = "wk1" ## x + 1 line will be logged as "wk1".
We need then an extra type which would store a name and a value of the expression :
type NamedExpression<'T> = {Value:'T ; Name: string}
Then we have to redefine an infix operator ## we use une computation expression :
let (##) name v = {Value = v; Name = name}
This operator just takes left and right part of the expression and wraps it within NamedExpression<'T> type.
We're not done yet. We have to modify the Bind part of our computation expression builder :
member this.Bind(x, f) =
let {Name = n; Value = v} = x
log v n
f v
First we deconstruct the NamedExpression<'T> value into name and wraped value. We log it and apply the function f to the unwrapped value v. Log function looks like that :
let log p n = printfn "'%s' has intermediate result of : %A" n p
Now when you run the workflow loggedWorkflow 10;; you get the following result :
'wk1' has intermediate result of : 11
'wk2' has intermediate result of : 12
'y' has intermediate result of : 13
Maybe there are better way to do that, something with compiler services or so, but this is the best attempt I could do so far.
If I understand you correctly, then there are several options:
let MyFunction1 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y,workingVariable1,workingVariable2
MyFunction1 2 |> printfn "%A"
type OneType()=
member val Y = 0 with get,set
member val WV1 = 0 with get,set
member val WV2 = 0 with get,set
override this.ToString() =
sprintf "Y: %d; WV1: %d; WV2: %d\n" this.Y this.WV1 this.WV2
let MyFunction2 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
new OneType(Y=y,WV1=workingVariable1,WV2=workingVariable2)
MyFunction2 2 |> printfn "%A"
Out:
(5, 3, 4)
Y: 5; WV1: 3; WV2: 4
http://ideone.com/eYNwYm
In the first function uses the tuple:
https://msdn.microsoft.com/en-us/library/dd233200.aspx
The second native data type.
https://msdn.microsoft.com/en-us/library/dd233205.aspx
It's not very "functional" way, but you can use mutable variable to store intermediate results:
let mutable workingVariable1 = 0
let mutable workingVariable2 = 0
let MyFunction x =
workingVariable1 <- x + 1
workingVariable2 <- workingVariable1 + 1
let y = workingVariable2 + 1
y