2010-01-02 24 views
23

(Làm thế nào) có thể đại diện cho các monads ở Scala theo cách tổng quát (như kiểu chữ Monad typeclass trong Haskell)? Có phải bằng cách nào đó có thể định nghĩa một số trait Monad cho mục đích này không?Tính trạng đơn lẻ trong Scala

Trả lời

40

Bạn có thể thử một cái gì đó như thế này:

trait Monad[+M[_]] { 
    def unit[A](a: A): M[A] 
    def bind[A, B](m: M[A])(f: A => M[B]): M[B] 
} 

// probably only works in Scala 2.8 
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new { 
    private val bind = tc.bind(m) _ 

    def map[B](f: A => B) = bind(f compose tc.unit) 

    def flatMap[B](f: A => M[B]) = bind(f) 
} 

implicit object MonadicOption extends Monad[Option] { 
    def unit[A](a: A) = Some(a) 

    def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f 
} 

Bạn sẽ đương nhiên xác định đối tượng tiềm ẩn tương tự cho bất kỳ đơn nguyên khác trái tim của bạn mong muốn. Trong thuật ngữ Haskell, bạn có thể nghĩ về Monad như typeclass và MonadicOption là một cá thể cụ thể của loại lớp đó. Việc chuyển đổi ngầm monadicSyntax chỉ đơn giản là chứng minh cách thức kiểu chữ này có thể được sử dụng để cho phép sử dụng Scala's for -comprehensions với bất kỳ thứ gì đáp ứng kiểu chữ Monad.

Nói chung, hầu hết mọi thứ trong thư viện chuẩn Scala triển khai flatMap là các đơn vị. Scala không định nghĩa một kiểu gõ Monad chung (mặc dù điều đó rất hữu ích). Thay vào đó, nó dựa trên một cú pháp cú pháp của trình phân tích cú pháp để cho phép sử dụng for -comprehensions với mọi thứ thực hiện các phương thức thích hợp. Cụ thể, các phương pháp đó là map, flatMapfilter (hoặc foreachfilter cho mẫu bắt buộc).

+0

Cảm ơn bạn, đây là chính xác những gì tôi đang tìm kiếm. Tôi chỉ muốn xác định các chức năng và máy biến áp chung một cách tổng quát ... – Dario

+3

Bạn sẽ không thực sự sử dụng nó cho bất cứ điều gì thực sự, đúng không? :-) Nghiêm túc, tôi đã làm việc với Scala trong một thời gian, và tôi thấy rằng rất nhiều trường hợp Haskell sẽ sử dụng kiểu chữ Monad chỉ không xuất hiện ở Scala vì các đặc điểm và phân loại. Các typeclass đưa ra ở trên, trong khi mát mẻ, chắc chắn sẽ không phải là cách thành ngữ để giải quyết vấn đề trong Scala. –

+1

Nhưng chúng xuất hiện. Họ đến tất cả các thời gian. Một vài lần một ngày, tôi muốn 'liftA2' hoặc' sequenceA'. Cấp, những điều này chỉ yêu cầu Áp dụng thay vì Monad, nhưng vẫn còn, nếu những điều này không xuất hiện trong lập trình của bạn thì bạn phải viết một cái gì đó rất đơn giản. – Apocalisp

14

Bạn có thể tìm thấy dự án scalaz thú vị; nó có rất nhiều công cụ (chức năng) khác ngoài việc thực hiện monads.

2

Scala đạt được sức mạnh tương tự cho các loại lớp của Haskell thông qua việc sử dụng các tham số ngầm định, đặc biệt là giới hạn xem và giới hạn ngữ cảnh. Bạn có thể thấy những thứ như vậy được sử dụng đặc biệt trên Scala 2.8, với các đặc điểm như OrderingNumeric.

Điều đó nói rằng, hãy xem dự án Scalaz. Nó có monads, functors, mũi tên ... toàn bộ shebang.

4

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

Dưới đây là một bài báo hữu ích và khá dài về các mô hình đơn nguyên và thực hiện nó trong Scala bởi Daniel, người viết được chấp nhận trả lời cho câu hỏi này.

(Đối với những người vấp ngã khi câu hỏi "cổ" này qua những cách thần bí của trang web tìm kiếm StackOverflow của.)

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