IO là một đơn nguyên như thế nào?


7

Tôi đang học ngôn ngữ lập trình Haskell. Từ những gì tôi đang đọc, Input / Ouput ( IO ) đặt ra những thách thức cho độ tinh khiết của Haskell, vì theo định nghĩa, chúng ta đang tương tác với thế giới bên ngoài. Từ Wikipedia:

Trong một ngôn ngữ chức năng thuần túy, chẳng hạn như Haskell, các chức năng không thể có bất kỳ tác dụng phụ có thể nhìn thấy bên ngoài như là một phần của ngữ nghĩa chức năng. Mặc dù một chức năng không thể trực tiếp gây ra hiệu ứng phụ, nhưng nó có thể xây dựng một giá trị mô tả hiệu ứng phụ mong muốn, mà người gọi nên áp dụng vào thời điểm thuận tiện.

Trong ký hiệu Haskell, giá trị của loại IO a đại diện cho một hành động mà khi được thực hiện sẽ tạo ra giá trị của loại a.

Chẳng mấy chốc, tôi biết rằng IO là một ví dụ về một đơn vị Haskell. Mặc dù chúng tôi không nhận được nhiều lời giải thích về các đơn vị là gì. Từ Functor, Ứng dụng và Monads trong hình ảnh

Cách tìm hiểu về Monads:

  1. Nhận bằng tiến sĩ khoa học máy tính.
  2. Vứt nó đi vì bạn không cần nó cho phần này!

Đến bây giờ, tôi đã đọc các định nghĩa khác nhau về - rằng họ thêm ngữ cảnh hoặc tạo các ngôn ngữ lập trình nhỏ hơn bên trong một ngôn ngữ lớn xung quanh một khái niệm cụ thể. Vẫn đang cố gắng để có được ý nghĩa về những gì các đơn nguyên và cách những ý tưởng đó áp dụng.

Trong Haskell, monadlà một kiểu chữ khác, về cơ bản chỉ có một quy tắc xác định nó. Và IOlà một ví dụ về điều đó.

class Monad m where    
    (>>=) :: m a -> (a -> m b) -> m b  

/programming/44965/what-is-a-monad

Có điều gì đó đại số đang diễn ra ở đây? Đại số về IO là gì?


Tôi xin lỗi vì ngôn ngữ cụ thể. Tôi hy vọng rằng hầu hết các cuộc thảo luận này áp dụng cho tất cả các ngôn ngữ lập trình chức năng. Bất kỳ lỗi nào trong cuộc thảo luận của tôi thể hiện sự hiểu biết hạn chế của riêng tôi về lĩnh vực này.

Có một định nghĩa khác về monad tôi tìm thấy trong nLab thậm chí không cụ thể đối với các ngôn ngữ lập trình.

Trong một câu hỏi riêng biệt, tôi muốn hiểu làm thế nào khái niệm lý thuyết thể loại của đơn nguyên khớp với định nghĩa CS trong trường hợp của Haskell.

Câu trả lời:


9

TLDR: Các loại và chức năng của Haskell tạo thành một thể loại và từ đó chúng tôi nhận thấy rằng mọi thứ với >>=returnđáp ứng các quy tắc cho các đơn nguyên.

Để xem xét ý nghĩa của một số loại là một phần của bộ ba đơn nguyên, trước tiên chúng ta phải xem xét một thể loại có nghĩa gì theo nghĩa Haskell.

Chúng tôi để thể loại của chúng tôi Haskđược xác định với các đối tượng là các loại và mũi tên Haskell là các hàm. Mỗi mũi tên nhận dạng là một ví dụ idvà thành phần là bình thường .. Thật tầm thường khi thấy rằng những điều này thỏa mãn các điều kiện kết hợp thông thường.

Bây giờ chúng ta có thể xem xét endofunctor trong Hask. Phần này chứa hai phần, một bản đồ từ loại đến loại và bản đồ từ chức năng đến chức năng để

  • map g . map f = = map (g . f)
  • map id = = id

Do đó, Functor là các hàm tạo kiểu (loại ánh xạ thành kiểu) được ghép với một hàm mapnâng mũi tên a -> bthành mũi tên F a -> F b. Chúng ta cũng có thể định nghĩa các phép biến đổi tự nhiên giữa chúng là một cái gì đó "trượt" thành viên của thành viên F ađể G athỏa mãn các điều kiện kết hợp thông thường

  • nat . fmap f = = fmap f . nat

Vì vậy, chúng ta có thể kết luận rằng một biến đổi tự nhiên là một cái gì đó với loại

nat :: forall a. F a -> G a

Cuối cùng, chúng tôi lưu ý rằng hàm tạo kiểu nhận dạng

type Id a = a

là một functor với bản đồ của nó được cung cấp bởi danh tính.

Bây giờ chúng tôi đang chuẩn bị để thảo luận về các đơn nguyên! Một đơn nguyên là một bộ ba gồm 3 điều,

  • Một chức năng F
  • Một sự chuyển đổi tự nhiên returngiữa IdF
  • Một sự chuyển đổi tự nhiên joingiữa F x FF

Với các điều kiện kết hợp đó join . fmap join = join . joinjoin . fmap return = join . return = id.

trong đó xphương tiện là sản phẩm của hai hàm tử được xác định bởi thành phần của các hàm tạo kiểu.

Các IOđơn nguyên có một . Đó là sự biến đổi tự nhiên đầu tiên của chúng tôi. Thứ hai của chúng tôi không hoàn toàn dễ dàng, nhưng chúng tôi có thể định nghĩa làreturn :: a -> IO a Id a -> IO ajoin

join :: IO (IO a) -> IO a
join = (>>= id)

Chúng ta có thể xem joinnhư là một hoạt động tuần tự. Nó nhận tất cả các hành động được lưu trữ trong cấu trúc của bên ngoài IOvà dán chúng trước tất cả các hành động ở bên trong IO, trả lại một hành động lớn hơn nhưng bằng phẳng IO a.

Vì vậy, về bản chất, chúng ta có khái niệm trừu tượng về các đơn nguyên trong lý thuyết thể loại và vì các loại Haskell có thể được xem như là một thể loại, chúng ta có thể áp dụng các khái niệm lý thuyết thể loại thông thường như các đơn nguyên và lấy các mẫu chung từ chúng. Đó là nó. Không có lý thuyết thể loại bí mật cho vay ý nghĩa cao hơn đối với các đơn vị ngoài các điều kiện kết hợp.

Đây thực sự là một mô hình khá phổ biến. Bất cứ khi nào chúng ta xem một cái gì đó với các thể loại, có thể là logic, ngữ nghĩa hoặc hệ thống loại, chúng ta có thể áp dụng một cách mù quáng 100 năm nghiên cứu cuối cùng vào danh mục mới của chúng ta và khám phá những khái niệm trừu tượng "mới".

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.