2017-09-11 12 views
5

Là một phần của việc học Scala Tôi cố gắng thực hiện chức năng lật của Haskell (hàm có chữ ký (A => B => C) = > (B => A => C)) trong Scala - và thực hiện nó như một hàm (sử dụng val) và không phải là phương thức (sử dụng def).là có thể thực hiện lật dưới dạng hàm Scala (và không phải là phương pháp)

tôi có thể thực hiện nó như một phương pháp, ví dụ như sau:

def flip[A, B, C](f: (A, B) => C):((B, A) => C) = (b: B, a: A) => f(a, b) 
val minus = (a: Int, b: Int) => a - b 
val f = flip(minus) 
println(f(3, 5)) 

Tuy nhiên, khi tôi cố gắng thực hiện nó như là một chức năng, nó không hoạt động:

val flip = (f: ((Any, Any) => Any)) => ((a: Any, b: Any) => f(b, a)) 
val minus = (a: Int, b: Int) => a - b 
val f = flip(minus) 
println(f(3, 5)) 

Khi tôi cố gắng biên dịch mã này, nó không thành công với thông báo này:

Error:(8, 18) type mismatch; 
found : (Int, Int) => Int 
required: (Any, Any) => Any 
val f = flip(minus) 

Tôi hiểu tại sao nó không thành công: Tôi cố gắng vượt qua (Int, Int) => Int trong đó (Bất kỳ, Bất kỳ) => Bất kỳ được mong đợi. Tuy nhiên, tôi không biết cách khắc phục vấn đề này. Có thể ở tất cả?

+0

'def something' có thể không phải là một hàm, nhưng nó trả về một hàm, có gì sai với điều đó? – pedrofurla

Trả lời

6

Scala không hỗ trợ các chức năng đa hình, không giống như các phương thức. Điều này là do tính chất giá trị hạng nhất của các hàm, chỉ đơn giản là các cá thể của các đặc tính FunctioN. Các hàm này là các lớp và chúng cần các kiểu được ràng buộc tại vị trí khai báo.

Nếu chúng ta mất phương pháp flip và cố gắng eta mở rộng nó vào một chức năng, chúng ta sẽ thấy:

val flipFn = flip _ 

Chúng tôi muốn trở lại để đổi lại một giá trị kiểu:

((Nothing, Nothing) => Nothing) => (Nothing, Nothing) => Nothing 

Do thực tế là không có loại nào bị ràng buộc, do đó trình biên dịch sẽ chuyển sang loại mông Nothing.

Tuy nhiên, không phải tất cả hy vọng đều bị mất. Có một thư viện được gọi là shapeless cho phép chúng tôi xác định các chức năng đa hình qua PolyN.

Chúng tôi có thể thực hiện lật như thế này:

import shapeless.Poly1 

object flip extends Poly1 { 
    implicit def genericCase[A, B, C] = at[(A, B) => C](f => (b: B, a: A) => f(a, b)) 
} 

flip không có khác biệt so với FunctionN đặc điểm, nó định nghĩa một phương pháp apply mà sẽ được gọi.

Chúng tôi sử dụng nó như thế này:

def main(args: Array[String]): Unit = { 
    val minus = (a: Int, b: Int) => a - b 
    val f = flip(minus) 
    println(f(3, 5)) 
} 

yielding:

2 

Điều này cũng sẽ làm việc cho String:

def main(args: Array[String]): Unit = { 
    val stringConcat = (a: String, b: String) => a + b 
    val f = flip(stringConcat) 
    println(f("hello", "world")) 
} 

yielding:

worldhello 
Các vấn đề liên quan