Related
i wanna sum 2 Int or 2 Double with using Generic.
fun <T> someFunction(a: T,b: T) {
Log.d(TAG, "${a+b}")
}
inline fun <reified T : Number> someFunction(a: T, b: T): T? {
return when {
a is Int && b is Int -> (a.toInt() + b.toInt()) as T
a is Double && b is Double -> (a.toDouble() + b.toDouble()) as T
else -> null
}
}
val resultInt = someFunction(2, 3) // value: 5 , type: Int?
val resultDouble = someFunction(2.25, 3.5) // value: 5.75, type: Double?
val resultMixed = someFunction(2, 3.5) // value: null, type: Number?
Unfortunately, there's no good way to do this.
While Number is a superclass of the numeric types, it's underspecified — all it lets you do is convert the value to one of the standard numeric types. It doesn't provide any way to to do arithmetic or other numeric operations.
(That may be because the types don't work. In traditional languages with many numeric types, such as C and Java, the result of an operation has a type which depends on both the operand types: adding a short and an int gives an int result. But there's no way to express that for class methods.)
So if you want to handle any Number, there are probably two approaches you can take.
Since the only thing Number provides is conversion it to a specific numeric type, one approach is to convert to the ‘best’ type, and do your arithmetic in that type. For example, if you only care about integer values, then you can call toLong() and do all your arithmetic with Longs.
For example:
fun <T> someFunction(a: T,b: T) {
Log.d(TAG, "${a.toLong() + b.toLong()}")
}
But this isn't a good general solution, because in general there isn't a ‘best’ type — whichever type you choose, there are some values it can't store. (Long is the largest integral type, but can't store fractions. And Double is the largest floating-point type, but can't store the full precision of Longs — for example, both Long.MAX_VALUE and Long.MAX-VALUE - 1 convert to the same Double value.) So whichever type you choose will risk some form of imprecision or rounding.
The other approach is to see which concrete types you have, and handle each combination separately. For example:
For example:
fun <T> someFunction(a: T,b: T) {
if ((a is Long && (b is Long || b is Int || b is Char || b is Short || b is Byte))
|| (b is Long && (a is Long || a is Int || a is Char || a is Short || a is Byte)))
Log.d(TAG, "${a.toLong() + b.toLong()}")
else if ((a is Int && (b is Int || b is Char || b is Short || b is Byte))
|| (b is Int && (a is Int || a is Char || a is Short || a is Byte)))
Log.d(TAG, "${a.toInt() + b.toInt()}")
else if ((a is Short && (b is Short || b is Byte))
|| (b is Short && (a is Short || a is Byte)))
Log.d(TAG, "${a.toShort() + b.toShort()}")
// …and so on, for all the other combinations you want to handle…
}
This gives you much finer control; but it's rarely used because it's far too long-winded and unwieldy for most situations. (And it won't cope with any new subclasses of Number that people write.)
So there's no good general approach to handling numbers in a generic fashion.
Instead, there are two specific approaches that people tend to take:
Pick a single concrete type, and use that. Often the requirements of your code dictate a suitable type (e.g. Int), and while it's nice to be generic, that's often not strictly needed.
Provide a Long version and a Double version. Between them, those types can hold all possible values from all the built-in numeric types, so one or other is normally sufficient for any particular use.
I think this might work for you
fun <T: Number> someFunction(a: T,b: T) {
val result = (a.toDouble()+b.toDouble()) as T
Log.d(TAG, "$result")
}
or if you want to return it
fun <T: Number> someFunction(a: T,b: T): T {
return (a.toDouble()+b.toDouble()) as T
}
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 often use standard function in cpp
sort(A.begin(),A.end(),mycmp)
where,
bool mycmp(int a, int b)
return (a>b);
to sort the vector A. But, when the question asks customized sorting then I often seem confused and take many tries to fix my compare function.Can someone explain that what exactly return (a>b); means; I read some posts also but still cant figure out how a>b determine the order to descending.
posts:
configure the compare function to work with std::sort
You can think cmp as an implementation of less than operator <. I use lt other than < after.
To simplify the question, assume we have bubble sort:
typedef bool (*cmp)(int, int);
bool inc(int a, int b) { return a < b; }
bool dec(int a, int b) { return a > b; }
void bubble_sort(int a[], int n, cmp lt) {
for (int i=0; i<n; ++i) {
for (int j=0; j+1<n-i; ++j) {
if (lt(a[j+1], a[j])) swap(a[j], a[j+1]);
}
}
}
a[j], a[j+1] swaps only if lt(a[j+1],a[j]) is true.
if we pass inc as comparing function, then lt(a[j+1],a[j]) is true means a[j+1]<a[j], so it sorts increasingly.
If we pass dec as comparing function, then lt(a[j+1],a[j]) is true means a[j+1]>a[j], so it sorts decreasingly.
You can check sgi sort implementation for more details.
https://www.sgi.com/tech/stl/sort.html
https://www.sgi.com/tech/stl/download.html
In Haskell, I know that if I define a function like this add x y = x + y
then I call like this add e1 e2. that call is equivalent to (add e1) e2
which means that applying add to one argument e1 yields a new function which is then applied to the second argument e2.
That's what I don't understand in Haskell. in other languages (like Dart), to do the task above, I would do this
add(x) {
return (y) => x + y;
}
I have to explicitly return a function. So does the part "yields a new function which is then applied to the second argument" automatically do underlying in Haskell? If so, what does that "hiding" function look like? Or I just missunderstand Haskell?
In Haskell, everything is a value,
add x y = x + y
is just a syntactic sugar of:
add = \x -> \y -> x + y
For more information: https://wiki.haskell.org/Currying :
In Haskell, all functions are considered curried: That is, all functions > in Haskell take just single arguments.
This is mostly hidden in notation, and so may not be apparent to a new
Haskeller. Let's take the function
div :: Int -> Int -> Int
which performs integer division. The expression div 11 2
unsurprisingly evaluates to 5. But there's more that's going on than
immediately meets the untrained eye. It's a two-part process. First,
div 11
is evaluated and returns a function of type
Int -> Int
Then that resulting function is applied to the value 2, and yields 5.
You'll notice that the notation for types reflects this: you can read
Int -> Int -> Int
incorrectly as "takes two Ints and returns an Int", but what it's
really saying is "takes an Int and returns something of the type Int
-> Int" -- that is, it returns a function that takes an Int and returns an Int. (One can write the type as Int x Int -> Int if you
really mean the former -- but since all functions in Haskell are
curried, that's not legal Haskell. Alternatively, using tuples, you
can write (Int, Int) -> Int, but keep in mind that the tuple
constructor (,) itself can be curried.)
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.