I'm looking through some notes that my professor gave regarding the language SML and one of the functions looks like this:
fun max gt =
let fun lp curr [] = curr
| lp curr (a::l) = if gt(a,curr)
then lp a l
else lp curr l
in
lp
end
Could someone help explain what this is doing? The thing that I am most confused about is the line:
let fun lp curr [] = curr
What exactly does this mean? As far as I can tell there is a function called lp but what does the curr [] mean? Are these arguments? If so, aren't you only allowed one parameter in sml?
It means that lp is a function that takes 2 parameters, the first being curr and the second being, well, a list, which logically, may be either empty ([]) or contain at least one element ((a::l) is a pattern for a list where a is at the head, and the rest of the list is l).
If one were to translate that bit of FP code into a certain well-known imperative language, it would look like:
function lp(curr, lst) {
if (lst.length == 0) {
return curr;
} else {
var a = lst[0]; // first element
var l = lst.slice(1, lst.length); // the rest
if (gt(a, curr)) {
return lp(a, l);
} else {
return lp(curr, l)
}
}
}
Quite a mouthful, but it's a faithful translation.
Functional languages are based on the Lambda Calculus, where functions take exactly one value and return one result. While SML and other FP languages are based on this theory, it's rather inconvenient in practice, so many of these languages allow you to express passing multiple parameters to a function via what is known as Currying.
So yes, in ML functions actually take only one value, but currying lets you emulate multiple arguments.
Let's create a function called add, which adds 2 numbers:
fun add a b = a + b
should do it, but we defined 2 parameters. What's the type of add? If you take a look in the REPL, it is val add = fn : int -> int -> int. Which reads, "add is a function that takes an int and returns another function (which takes an int and returns an int)"
So we could also have defined add this way:
fun add a =
fn b => a + b
And you will see that they are alike. In fact it is safe to say that in a way,
the former is syntactic sugar for the later.
So all functions you define in ML, even those with several arguments, are actually functions with one argument, that return functions that accept the second argument and so on. It's a little hard to get used to at first but it
becomes second nature very soon.
fun add a b = a + b (* add is of type int -> int -> int *)
add 1 2 (* returns 3 as you expect *)
(* calling add with only one parameter *)
val add1 = add 1
What's add1? It is a function that will add 1 to the single argument you pass it!
add1 2 (* returns 3 *)
This is an example of partial application, where you are calling a function piecemeal,
one argument at a time, getting back each time, another function that accepts the rest
of the arguments.
Also, there's another way to give the appearance of multiple arguments: tuples:
(1, 2); (* evaluates to a tuple of (int,int) *)
fun add (a,b) = a + b;
add (1, 2) (* passing a SINGLE argument to a function that
expects only a single argument, a tuple of 2 numbers *)
In your question, lp could have also been implemented as lp (curr, someList):
fun max gt curr lst =
let fun lp (curr, []) = curr
| lp (curr, (a::l)) = if gt(a,curr) then lp (a, l)
else lp (curr, l)
in
lp (curr, lst)
end
Note that in this case, we have to declare max as max gt curr lst!
In the code you posted, lp was clearly implemented with currying. And the type of
max itself was fn: ('a * 'a -> bool) -> 'a -> 'a list -> 'a. Taking that apart:
('a * 'a -> bool) -> (* passed to 'max' as 'gt' *)
'a -> (* passed to 'lp' as 'curr' *)
'a list -> (* passed to 'lp' as 'someList' *)
'a (* what 'lp' returns (same as what 'max' itself returns) *)
Note the type of gt, the first argument to max: fn : (('a * 'a) -> bool) - it is a function of one argument ('a * 'a), a tuple of two 'a's and it returns an 'a. So no currying here.
Which to use is a matter of both taste, convention and practical considerations.
Hope this helps.
Just to clarify a bit on currying, from Faiz's excellent answer.
As previously stated SML only allows functions to take 1 argument. The reason for this is because a function fun foo x = x is actually a derived form of (syntactic sugar) val rec foo = fn x => x. Well actually this is not entirely true, but lets keep it simple for a second
Now take for example this power function. Here we declare the function to "take two arguments"
fun pow n 0 = 1
| pow n k = n * pow n (k-1)
As stated above, fun ... was a derived form and thus the equivalent form of the power function is
val rec pow = fn n => fn k => ...
As you might see here, we have a problem expressing the two different pattern matches of the original function declaration, and thus we can't keep it "simple" anymore and the real equivalent form of a fun declaration is
val rec pow = fn n => fn k =>
case (n, k) of
(n, 0) => 1
| (n, k) => n * pow n (k-1)
For the sake of completeness, cases is actually also a derived form, with anonymous functions as the equivalent form
val rec pow = fn n => fn k =>
(fn (n,0) => 1
| (n,k) => n * pow n (k-1)) (n,k)
Note that (n,k) is applied directly to the inner most anonymous function.
Related
A function can be a highly nested structure:
function a(x) {
return b(c(x), d(e(f(x), g())))
}
First, wondering if a function has an instance. That is, the evaluation of the function being the instance of the function. In that sense, the type is the function, and the instance is the evaluation of it. If it can be, then how to model a function as a type (in some type-theory oriented language like Haskell or Coq).
It's almost like:
type a {
field: x
constructor b {
constructor c {
parameter: x
},
...
}
}
But I'm not sure if I'm not on the right track. I know you can say a function has a [return] type. But I'm wondering if a function can be considered a type, and if so, how to model it as a type in a type-theory-oriented language, where it models the actual implementation of the function.
I think the problem is that types based directly on the implementation (let's call them "i-types") don't seem very useful, and we already have good ways of modelling them (called "programs" -- ha ha).
In your specific example, the full i-type of your function, namely:
type a {
field: x
constructor b {
constructor c {
parameter: x
},
constructor d {
constructor e {
constructor f {
parameter: x
}
constructor g {
}
}
}
}
is just a verbose, alternative syntax for the implementation itself. That is, we could write this i-type (in a Haskell-like syntax) as:
itype a :: a x = b (c x) (d (e (f x) g))
On the other hand, we could convert your function implementation to Haskell term-level syntax directly to write it as:
a x = b (c x) (d (e (f x) g))
and the i-type and the implementation are exactly the same thing.
How would you use these i-types? The compiler might use them by deriving argument and return types to type-check the program. (Fortunately, there are well known algorithms, such as Algorithm W, for simultaneously deriving and type-checking argument and return types from i-types of this sort.) Programmers probably wouldn't use i-types directly -- they're too complicated to use for refactoring or reasoning about program behavior. They'd probably want to look at the types derived by the compiler for the arguments and return type.
In particular, "modelling" these i-types at the type level in Haskell doesn't seem productive. Haskell can already model them at the term level. Just write your i-types as a Haskell program:
a x = b (c x) (d (e (f x) g))
b s t = sqrt $ fromIntegral $ length (s ++ t)
c = show
d = reverse
e c ds = show (sum ds + fromIntegral (ord c))
f n = if even n then 'E' else 'O'
g = [1.5..5.5]
and don't run it. Congratulations, you've successfully modelled these i-types! You can even use GHCi to query derived argument and return types:
> :t a
a :: Floating a => Integer -> a -- "a" takes an Integer and returns a float
>
Now, you are perhaps imagining that there are situations where the implementation and i-type would diverge, maybe when you start introducing literal values. For example, maybe you feel like the function f above:
f n = if even n then 'E' else 'O'
should be assigned a type something like the following, that doesn't depend on the specific literal values:
type f {
field: n
if_then_else {
constructor even { -- predicate
parameter: n
}
literal Char -- then-branch
literal Char -- else-branch
}
Again, though, you'd be better off defining an arbitrary term-level Char, like:
someChar :: Char
someChar = undefined
and modeling this i-type at the term-level:
f n = if even n then someChar else someChar
Again, as long as you don't run the program, you've successfully modelled the i-type of f, can query its argument and return types, type-check it as part of a bigger program, etc.
I'm not clear exactly what you are aiming at, so I'll try to point at some related terms that you might want to read about.
A function has not only a return type, but a type that describes its arguments as well. So the (Haskell) type of f reads "f takes an Int and a Float, and returns a List of Floats."
f :: Int -> Float -> [Float]
f i x = replicate i x
Types can also describe much more of the specification of a function. Here, we might want the type to spell out that the length of the list will be the same as the first argument, or that every element of the list will be the same as the second argument. Length-indexed lists (often called Vectors) are a common first example of Dependent Types.
You might also be interested in functions that take types as arguments, and return types. These are sometimes called "type-level functions". In Coq or Idris, they can be defined the same way as more familiar functions. In Haskell, we usually implement them using Type Families, or using Type Classes with Functional Dependencies.
Returning to the first part of your question, Beta Reduction is the process of filling in concrete values for each of the function's arguments. I've heard people describe expressions as "after reduction" or "fully reduced" to emphasize some stage in this process. This is similar to a function Call Site, but emphasizes the expression & arguments, rather than the surrounding context.
I tried to write the Kleisli exponentiation in Kotlin:
fun <A,B> kleisli(n: Int, f: (A) -> B): (A) -> B = if (n == 1) f else { it -> f(kleisli(n-1, ::f)(it)) }
that just composes f, n times (please do not put n = 0 in my code).
Kotlin (1.0.6) complains error: unsupported [References to variables aren't supported yet] pointing at the ::f.
Am I doing something wrong?
Use just f instead of ::f, it is already a functional value (i.e. a parameter, a variable or a property of a functional type), so you don't need to make a callable reference of it.
... else { it -> f(kleisli(n - 1, f)(it)) }
Also, your example seems to have a type mismatch: kleisli(n - 1, f) returns a function of type (A) -> B, which is called on it of type A, returning a result of type B. Then the result is passed to f, but f can only receive A. To fix that, you can remove type parameter B and leave only A:
fun <A> kleisli(n: Int, f: (A) -> A) : (A) -> A =
if (n == 1)
f else
{ it -> f(kleisli(n - 1, f)(it)) }
(runnable demo of this code)
Also, this code demonstrates the intention perfectly well in functional style, but it might result into redundant objects allocation and undesired call stack growth. It can, however, be rewritten into imperative style, which will work more efficiently:
fun <T> iterativeKleisli(n: Int, f: (T) -> T) : (T) -> T = { x ->
var result = x
for (i in 1..n)
result = f(result)
result
}
[...] a pair of functions tofun : int -> ('a -> 'a) and fromfun : ('a -> 'a) ->
int such that (fromfun o tofun) n evaluates to n for every n : int.
Anyone able to explain to me what this is actually asking for? I'm looking for more of an explanation of that than an actual solution to this.
What this is asking for is:
1) A higher-order function tofun which when given an integer returns a polymorphic function, one which has type 'a->'a, meaning that it can be applied to values of any type, returning a value of the same type. An example of such a function is:
- fun id x = x;
val id = fn : 'a -> 'a
for example, id "cat" = "cat" and id () = (). The later value is of type unit, which is a type with only 1 value. Note that there is only 1 total function from unit to unit (namely, id or something equivalent). This underscores the difficulty with coming up with defining tofun: it returns a function of type 'a -> 'a, and other than the identity function it is hard to think of other functions. On the other hand -- such functions can fail to terminate or can raise an error and still have type 'a -> 'a.
2) fromfun is supposed to take a function of type 'a ->'a and return an integer. So e.g. fromfun id might evaluate to 0 (or if you want to get tricky it might never terminate or it might raise an error)
3) These are supposed to be inverses of each other so that, e.g. fromfun (tofun 5) needs to evaluate to 5.
Intuitively, this should be impossible in a sufficiently pure functional language. If it is possible in SML, my guess is that it would be by using some of the impure features of SML (which allow for side effects) to violate referential transparency. Or, the trick might involve raising and handling errors (which is also an impure feature of SML). If you find an answer which works in SML it would be interesting to see if it could be translated to the annoyingly pure functional language Haskell. My guess is that it wouldn't translate.
You can devise the following property:
fun prop_inverse f g n = (f o g) n = n
And with definitions for tofun and fromfun,
fun tofun n = ...
fun fromfun f = ...
You can test that they uphold the property:
val prop_test_1 =
List.all
(fn i => prop_inverse fromfun tofun i handle _ => false)
[0, ~1, 1, valOf Int.maxInt, valOf Int.minInt]
And as John suggests, those functions must be impure. I'd also go with exceptions.
The type of this function is T -> (T -> U) -> U. I believe that in Haskell, it would be something like ($ . flip).
Or, from an object-oriented perspective (which is the way I've been looking at it):
type T {
U myFunction(f: T -> U) {
return f(this);
}
}
I've been calling it "into" in my notes, and using a single arrow (->) as an operator. It's analogous to the map function, but for a scalar:
a.into f = f(a)
[a, b, c].map f = [f(a), f(b), f(c)]
Examples of practical applications:
42 -> Math.sqrt
foo.bar.into(doSomething).baz.into(doSomethingElse).xyzzy
(rather than doSomethingElse(doSomething(foo.bar).baz).xyzzy)
It looks like F# has this function. The function doesn't seem to be named, but the operators is known as the pipeline operator. http://msdn.microsoft.com/en-us/library/dd233229.aspx
let result = 100 |> function1 |> function2
In Haskell, it is flip id. A certain facetious package called data-aviary defines it as thrush. Is there an inverse of the Haskell $ operator?
"Write a function lv: cfg -> (blabel -> ide set), which computes the live variables analysis on the given control flow graph."
Having cfg and blabel defined and ide set as a list of string, how can I create a function with that signature?
You're presumably familiar with the let syntax to define a function:
let f x = x + 1 in …
You can use this syntax anywhere, including in a function body. Now if you happen to use the inner function's name as the return value of the outer function, the outer function will be returning a function.
let outer_function x =
let inner_function y = x + y in
inner_function
The let syntax is in fact syntactic sugar for fun or function. In particular, if you define inner_function just to use the name once, you might as well use the fun notation and not bother giving the inner function a name.
let outer_function x =
fun y -> x + y
Furthermore, if all the outer function does when you pass it an argument is to build and return an inner function, then consider its behavior when you pass that function two arguments. First the outer function builds an inner function, using its first (and only) argument; then that inner function is applied to the second argument, so its body is executed. This is equivalent to having just one function that takes two arguments. This
observation is known as currying.
let outer_function x y = x + y
Note that the type of this function is int -> int -> int; this is the same type as int -> (int -> int) (the arrow type operator is right-associative).
Currying doesn't apply when the outer function does some work before building the inner function. In that case, the work is performed after receiving the first argument.
let outer_function x =
print_endline "outer";
fun y -> print_endline "inner"; x + y
So the structure of your code is likely to look like this:
let lv (c : cfg) : blabel -> ide set =
let c' = do_some_precomputation c in
fun (bl : blabel) -> (… : ide set)