2012-12-07 30 views
14

Tôi thích bám sát nhất có thể vào mô hình chức năng, ép gần như tôi có thể đi đến chức năng thuần túy khi bộ não của tôi chuẩn bị cho thử thách. Tôi sử dụng F # khi có thể. Thông thường, tôi bị mắc kẹt với một trong hai VB.NET hoặc C# (hoặc VBA, khi tôi thực sự không may mắn). Vì vậy, ngôn ngữ của tôi cho phép tôi đi lạc khá xa cách tiếp cận chức năng.Việc đăng nhập từ bên trong một Lập trình Chức năng Paradigm

Trước đây tôi đã bỏ qua ghi nhật ký và liên lạc với người dùng cho đến khi tôi có kết quả - chỉ cần để người dùng chờ. Bây giờ tôi đang cố gắng thực hiện ghi nhật ký và/hoặc cập nhật các thanh trạng thái. Thật dễ dàng, bởi vì ngôn ngữ của tôi cho phép tôi viết vào đầu ra tiêu chuẩn bất cứ khi nào tôi muốn. Nhưng từ một quan điểm thuần túy chức năng, làm thế nào người ta đi về việc rò rỉ thông tin về những gì đang xảy ra bên trong chức năng của một người với thế giới bên ngoài? Việc đăng nhập hoặc giao tiếp với người dùng trong khi tính toán có đơn giản là trái ngược với cách tiếp cận thuần túy không?

Tôi chắc chắn trong Haskell người ta sẽ sử dụng một Monad. Còn khi sử dụng các ngôn ngữ khác thì sao?

Cảm ơn.

+0

'Tôi thích gắn bó càng gần với mô hình chức năng, ép càng gần như tôi có thể nhận được để hoàn toàn chức năng khi bộ não của tôi là cho thách thức' sử dụng nó khi nó mang lại cho bạn một số lợi ích. Mã chức năng thuần túy thường có thể thêm sự phức tạp ngẫu nhiên vào hệ thống. –

+0

Đó có lẽ là lời khuyên tốt ... –

Trả lời

8

Hãy có một cái nhìn tại giải pháp monadic Haskell. Ý tưởng đằng sau việc ghi nhật ký là các tính toán của chúng tôi có một phương thức bổ sung để viết một thông điệp ở đâu đó "ngoài". Có rất nhiều cách làm thế nào để đại diện cho tính toán như vậy, nhưng một trong những chung nhất là để thực hiện một đơn nguyên:

class (Monad m) => MonadWriter w m | m -> w where 
    tell :: w -> m() 

Loại w đại diện cho các thông điệp và chức năng tell là những gì "gửi" một thông điệp vào một monadic (effect- đầy đủ) tính toán.

Ghi chú:

  • Haskell của MonadWriter thực sự là phong phú hơn, nó có chứa các chức năng cho phép để kiểm tra và sửa đổi w, nhưng chúng ta hãy giữ cho rằng dành cho bây giờ.
  • Phần | m -> w không thực sự quan trọng đối với giải thích, điều đó chỉ có nghĩa là w được sửa cho m nhất định.

Việc triển khai thường được sử dụng nhất là Writer, về cơ bản chỉ là một cặp.Một phần tử của nó là kết quả của việc tính toán và phần tử kia là một chuỗi các thông báo bằng văn bản. (Trên thực tế nó không thực sự là một chuỗi, nó tổng quát hơn - một monoid, xác định các hoạt động để kết hợp nhiều thông điệp thành một.) Bạn có thể kiểm tra giải pháp của Haskell bằng cách xem Writer module. Tuy nhiên nó được viết chung hơn, bằng cách sử dụng WriterT biến áp đơn nguyên, vì vậy nếu bạn không phải là một fan hâm mộ đơn điệu, nó có thể được khá khó đọc. Điều tương tự cũng có thể được thực hiện bằng các ngôn ngữ chức năng khác, ví dụ: xem this example in Scala.

Nhưng có thể thực hiện các tác dụng phụ có thể có khác, có tác dụng phụ hơn (vẫn hoạt động) của lớp loại ở trên. Chúng ta có thể xác định tell để phát ra thông điệp đến một số bồn rửa bên ngoài, giống như stdout, vào một tập tin, vv Ví dụ:

{-# LANGUAGE FunctionalDependencies, TypeSynonymInstances, FlexibleInstances #-} 

instance MonadWriter String IO where 
    tell = putStrLn 

Ở đây chúng ta nói rằng IO có thể được sử dụng như một cơ sở khai thác gỗ mà viết String s vào stdout . (Đây chỉ là một ví dụ đơn giản, việc triển khai đầy đủ có thể có một máy biến áp đơn lẻ có thể thêm tell chức năng vào bất kỳ đơn vị IO nào.)

+0

Lớp học và đồ vật? Whaaaat? Đó không phải là mô hình lập trình chức năng, đó chỉ là OOP trong FP. –

+4

Tôi không thấy điểm, loại các lớp trong Haskell khá khác với các lớp OO. –

+0

Cảm ơn bạn. Có thể tôi cũng không thấy điểm đó. Trong câu trả lời này, không có trường hợp sử dụng nào của lớp. Xin vui lòng, tập trung vào phía khách hàng sử dụng đăng nhập thay vì thư viện. Cảm ơn bạn! –

3

Tôi mới để lập trình chức năng, nhưng đây là một nỗ lực trong Scala:

object FunctionalLogging { 

    type Result = Int 

    class ResultWithLogging(val log: List[String], val result: Result) {} 

    def functionWithLogging(log: List[String], arg: String): ResultWithLogging = { 
    def function(arg: String): Result = arg.length 

    new ResultWithLogging(log :+ ("Calling function(" + arg +")"), function(arg)) 
    } 

    val result = functionWithLogging(List(), "Hello world!") 

    // -- Pure functional code ends here -- 
    println("Result = " + result.result) 
    println("Log = " + result.log) 
} 

Đó là chức năng trong đó không có tác dụng phụ, nhưng rõ ràng nhật ký là một phần của các đối số chức năng và lợi nhuận, vì vậy nó không phải là rất thanh lịch hoặc thực tế. Dường như với tôi rằng việc ghi nhật ký là một tác dụng phụ mong muốn theo định nghĩa, vì vậy nếu bạn đi cùng với định nghĩa của tôi thì câu hỏi là làm thế nào để cô lập các chức năng không có chức năng khỏi mã chức năng. Trong thực tế, tôi có thể bắt đầu với một đối tượng Scala (có thể quá giống như một singleton - một đặc điểm có lẽ là Scala tốt hơn), hoặc một diễn viên để tích lũy các thông điệp đăng nhập và làm bất cứ điều gì cần phải được thực hiện với chúng.

Đây là một cái nhìn thực tế hơn: Logging in Scala

Sửa

Câu hỏi này nói về Haskell Monads và IO: What other ways can state be handled in a pure functional language besides with Monads?

+0

Tôi thích quy trình suy nghĩ của bạn ở đây. Tuy nhiên, trong trường hợp của tôi, hàm này khá dài, và tôi muốn báo cáo khi nó được xử lý, thay vì chờ đợi sự trở lại của nó để báo cáo nhật ký của nó. Tuy nhiên, nếu không ai khác trả lời câu hỏi của tôi, tôi có thể đánh dấu câu trả lời này, bởi vì, trong khi câu trả lời Haskell là câu trả lời tuyệt vời, câu hỏi của tôi cụ thể hơn về cách tiếp cận không phải Monad. Cảm ơn! –

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