please, check my snippet, the question is there (my english is too bad to be able to explain my trouble by the words :))
func flip1<A, B, C>(f : ((A, B) -> C), _ b : B, _ a : A) -> C {
return f(a, b)
}
flip1(-, 2, 1) // -1
flip1(/, 2.0, 3.0) // 1.5
// partialy curried version
func flip2<A, B, C>(f : (A, B) -> C, _ i : B, _ j : A) -> C {
return f(j, i)
}
print(flip2(- , 2, 1)) // -1
print(flip2(/,2.0,3.0)) // 1.5
compiles without trouble, but how to use it???
// full curried version
// compiles without trouble, but how to use it???
func flip3<A, B, C>(f : A -> B -> C) -> B -> A -> C {
return { b in { a in f(a)(b) } }
}
/*
* flip3(/)(2.0)(3.0)
*
* error: ambiguous reference to member '/'
* it meands there are more than one candidate for / function
*/
// we need curried version of /, let's define it
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
/*
* let divideUnknownType = curry(/)
* compiler still complain, as expected :-)
* error: ambiguous use of operator '/'
*/
// and then define the type of it
let divideDoubles: Double->Double->Double = curry(/)
let divideIntegers: Int->Int->Int = curry(/)
// :-)
print(flip3(divideDoubles)(2.0)(3.0)) // 1.5
print(flip3(divideDoubles)(2)(3)) // 1.5
print(flip3(divideIntegers)(2)(3)) // 1
as you can see, it breaks my 'generic' approach. any idea how to solve it?
func flip3<A, B, C>(f: (A, B) -> C) -> B -> A -> C {
return { b in { a in f(a, b) } }
}
flip3(/)(2.0)(3.0) // 1.5
Related
This is my code:
import UIKit
func gcd(_ a: Int, _ b: Int) -> (Int) {
if a == b {
return a
} else if a > b {
gcd(a - b, b)
} else {
gcd(a, b - a)
}
}
gcd(9, 6)
The algorithm works like this:
9
6
3
6
3
3
It gives me a correct answer when I do print(a) but It does not give me the result when I do return.
You miss return in the last 2 cases
func gcd(_ a: Int, _ b: Int) -> Int {
if a == b {
return a
} else if a > b {
return gcd(a - b, b)
} else {
return gcd(a, b - a)
}
}
To call
print(gcd(9, 6))
In the below example, why is the foo(f) call ambiguous?
I understand that the second overload could also apply with P == (),
but why isn't the first one considered more specialized,
and therefore a better match?
func foo<R>(_ f: () -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
let f: () -> Int = { 42 }
foo(f) // "Ambiguous use of 'foo'"
I'd say your problem is that you don't explicitely tell the compiler that P == ()
try the following code in a playground :
Void.self == (Void).self // true
Void() == () // true
(Void)() == () // true
(Void) == () // Cannot convert value of type '(Void).Type' to expected argument type '()'
Foo<Int>.self == (() -> Int).self // false
(() -> Int).self == ((Void) -> Int).self // false
Foo<Int>.self == ((Void) -> Int).self // true
Since (Void) cannot be converted to (), I guess the compiler can't understand that foo<R>(_ f: () -> R) is actually a specialization of foo<P, R>(_ f: (P) -> R).
I suggest you create generic type aliases for your function types to help the compiler understand what you're doing eg. :
typealias Bar<P, R> = (P) -> R
typealias Foo<R> = Bar<Void, R>
Now you can can define your function like that :
func foo<R>(_ f: Foo<R>) { print("r") } // Note that this does not trigger a warning.
func foo<P, R>(_ f: Bar<P, R>) { print("pr") }
and then use them with any closure you want :
let f: () -> Int = { 42 }
foo(f) // prints "r"
let b: (Int) -> Int = { $0 }
foo(b) // prints "pr"
let s: (String) -> Double = { _ in 0.0 }
foo(s) // prints "pr"
But you can actually just write :
func foo<R>(_ f: (()) -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }
or even :
func foo<R>(_ f: (Void) -> R) { print("r") } // triggers warning :
// When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
func foo<P, R>(_ f: (P) -> R) { print("pr") }
and you get the same results.
I was going through this blog. When I tried write curry function on my own method:
func stdCurry(f : (A,B) -> C) -> (A)->(B->C) {
return { (a:A) ->(B -> C) in {
(b:B) -> C in
{
return f(a,b)
}
}
}
}
I got an error:
:7:22: error: declared closure result 'C' is incompatible with contextual type '_'
(b:B) -> C in
^
_
But when I remove the flower parentheses around trailing closure then it won't report any error. Can anybody help me to understand this.
The inner curly braces -> in { ... } tells swift that this inner part is a closure, whereas it in fact only contains a value (the C type evaluation of f(a,b)). If you remove these inner curly braces, your example work.
E.g., try
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B -> C) {
return { (a:A) -> (B -> C) in {
(b:B) -> C in
return f(a,b) // <-- this is not a closure (just returns a value of type C`
}
}
}
Note that I've added the generic types to the function signature above (perhaps you function is part of a class and you get your types A, B and C from there).
To make the error above more clear, consider this a bit simpler example (taking a closure and returning it):
/* This is ok */
func myClosure<A,B>(f: (A) -> B) -> (A) -> B {
return {
x in f(x)
}
}
/* Error: return type here is not (A) -> B, but contains
an anonymous closure () -> B */
func myClosure<A,B>(f: (A) -> B) -> (A) -> B {
return {
x in { f (x) }
}
}
/* Ok */
func myClosure<A,B>(f: (A) -> B) -> (A) -> (() -> B) {
return {
x in { f(x) }
}
}
Also note that since Swift knows (infers)---from your function signature---the types in as well as what type/closure to expect in return for each in ... statment, you can omit the closure type ((a:A) -> (B -> C)) as well as the return keyword and make your expression more compact as follows:
func stdCurry<A, B, C>(f: (A, B) -> C) -> A -> (B -> C) {
return { a in { b in f(a, b) } }
}
At your request in the comments below: you can make use of "multiple statements" in the tail e.g. by using the approach of the third "simple example" above, e.g.:
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) -> () -> C {
return { (a:A) -> (B -> () -> C) in {
(b:B) -> () -> C in
return {
// ...
f(a,b)
}
}
}
}
Note that as the function signature grows somewhat "messy", it's favourable to omit these details in the actual closures of your function, i.e.:
func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) -> () -> C {
return { a in {
b in
return {
// ...
f(a,b)
}
}
}
}
I want to write a flip method in Swift.
Here is the signature.
Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c
My code in Swift:
func flip1<A, B, C>(f: A->B->C) -> (B->A->C) {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
func flip2<A, B, C>(f: A->B->C) -> (B->A->C) {
return { (valueB: B) in
return { (valueA: A) in
return f(valueA)(valueB)
}
}
}
The flip1 method can not compile. There is an error Extra argument in call at line return f(valueA, valueB)
The flip2 method works fine, except the flipped method can only be called like this method(1)(2).
How to write the flip method so that I can use the flipped method like method(1, 2) and method(1)(2)?
A->B->C is the type of a function taking one argument of type A
and returning a function B->C (a "curried" function). The type of a function taking
two arguments is (A, B)->C:
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
let x = flip(-)(10, 5)
println(x) // -5
It can slightly be shortened to
func flip<A, B, C>(f: (A, B)->C) -> (B, A)->C {
return { (valueB, valueA) in
f(valueA, valueB)
}
}
due to automatic type inference.
As far as I know, Swift does not automatically convert functions
taking multiple arguments into curried functions, compare
Typecase regular Swift function to Curry Function.
This is the #MartinR answer updated to Swift 5.1
func flip<A, B, C>(_ f: #escaping (A, B)->C) -> (B, A)->C {
return { (valueB: B, valueA: A) in
return f(valueA, valueB)
}
}
let x = flip(-)(10, 5) println(x) // -5
It can slightly be shortened to
func flip<A, B, C>(_ f: #escaping (A, B)->C) -> (B, A)->C {
{ (valueB: B, valueA: A) in
f(valueA, valueB)
}
}
I'm trying to use scala's LinkedHashMap as an LRU cache, but I'm not sure how to remove the oldest entry of such a map. I know java's LinkedHashMap has a method removeEldestEntry, but there does not seem to be a similar method for scala's implementation. I'd prefer not to convert to java's implementation just to have access to removeEldestEntry. How can I achieve this?
This will do what you want:
def removeOldestEntry[K](m: scala.collection.mutable.LinkedHashMap[K, _]): m.type =
m -= m.head._1
(Kudos to Jasper-M for pointing out that head will give the oldest entry)
You can do this in the following way:
object myApp {
def main(args: Array[String]) {
val myMap = new MyLinkedHashMap[Int,String]()
myMap.add(1, "a") // Map(1 -> a)
myMap.add(2, "b") // Map(1 -> a, 2 -> b)
myMap.add(3, "c") // Map(1 -> a, 2 -> b, 3 -> c)
myMap.add(4, "d") // Map(1 -> a, 2 -> b, 3 -> c, 4 -> d)
myMap.removeEldest // Map(2 -> b, 3 -> c, 4 -> d)
myMap.get(2) // Map(3 -> c, 4 -> d, 2 -> b)
myMap.removeEldest // Map(4 -> d, 2 -> b)
}
}
class MyLinkedHashMap[K,V] {
import scala.collection.mutable.LinkedHashMap
var map = new LinkedHashMap[K, V]()
/* adds an element to the HaskMap */
def add(key: K, value: V) {
map.put(key, value)
}
/* removes the LRU element from the HaskMap */
def removeEldest {
if (!map.isEmpty) {
map = map.drop(1)
}
}
/* gets the value for the given key and moves it to the top of the HashMap */
def get(key: K): Option[V] = {
val value = map.remove(key)
if (value != None) {
map.put(key, value.get)
}
return value
}
}