Tại sao Haskell's Prelude.read không trả về Có thể?


108

Có lý do chính đáng tại sao loại Prelude.read là

read :: Read a => String -> a

thay vì trả về một Maybegiá trị?

read :: Read a => String -> Maybe a

Vì chuỗi có thể không thể phân tích cú pháp Haskell, nên không phải chuỗi sau sẽ tự nhiên hơn?

Hoặc thậm chí là một Either String a, nơi Leftsẽ chứa chuỗi ban đầu nếu nó không phân tích cú pháp và Rightkết quả nếu có?

Biên tập:

Tôi không cố gắng để người khác viết một trình bao bọc tương ứng cho tôi. Chỉ cần tìm kiếm sự đảm bảo rằng sẽ an toàn khi làm như vậy.


14
Tại sao không takechấp nhận bất kỳ Num a => a? Tại sao có một trường hợp đặc biệt của fmapdanh sách? Tại sao Functorkhông bắt buộc đối với các Monadtrường hợp? Tôi mong đợi câu trả lời tương tự như câu trả lời cho những câu hỏi này và những câu hỏi liên quan.

3
Chà, đó là lý do tại sao tôi diễn giải nó theo cách tôi đã làm, để ngỏ tùy chọn mà không có lý do chính đáng. Mặc dù tôi cũng nghi ngờ rằng có thể không có, như đối với các ví dụ nổi tiếng mà bạn đưa ra, nhưng bạn nên yêu cầu để đảm bảo rằng việc viết trình bao bọc của riêng tôi sẽ không tạo ra các vấn đề không lường trước được ở phía sau.
Bilal Barakat

Tôi hy vọng một readMaybechức năng sẽ sớm được thêm vào.
augustss

Điểm tốt @delnan, nhưng không takenên Integral n => n -> [a] -> [a]?
Doug McClean 10/11/11

@DougMcClean: Đúng, thực ra là vậy Integral, không phải Num- rắm não.

Câu trả lời:


106

Chỉnh sửa : Kể từ GHC 7.6, readMaybecó sẵn trong Text.Readmô-đun trong gói cơ sở, cùng với readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


Câu hỏi tuyệt vời! Bản thân kiểu đọc sẽ không sớm thay đổi vì điều đó sẽ phá vỡ rất nhiều thứ. Tuy nhiên, cần phải có một maybeReadchức năng.

Tại sao không có? Câu trả lời là "sức ỳ". Có một cuộc thảo luận vào năm '08 đã bị trật bánh bởi một cuộc thảo luận về "fail".

Tin tốt là mọi người đã đủ thuyết phục để bắt đầu tránh thất bại trong các thư viện. Tin xấu là đề xuất đã bị mất trong quá trình xáo trộn. Cần phải có một hàm như vậy, mặc dù một hàm rất dễ viết (và có rất nhiều phiên bản giống nhau trôi nổi trên nhiều cơ sở mã).

Xem thêm thảo luận này .

Cá nhân, tôi sử dụng phiên bản từ gói an toàn .


30

Vâng, sẽ rất hữu ích với hàm đọc trả về Có thể. Bạn có thể tự làm một cái:

readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
              [(x, "")] -> Just x
              _ -> Nothing

3
Cảm ơn bạn! Tôi hy vọng bản chỉnh sửa không nghe có vẻ vô ơn! :) Chỉ muốn làm cho nó rõ ràng Tôi không yêu cầu ra khỏi sự lười biếng ...
Bilal Barakat

6
Nếu @augustss không thể cung cấp thì câu trả lời tốt hơn có thể không tồn tại.
John L

2
Tôi không nghĩ rằng một phiên bản có thể đã từng được thảo luận trong thiết kế ban đầu. Nhiều điều trong số này trở nên hiển nhiên với kinh nghiệm, nhưng có thể khó dự đoán.
augustss

Các lý do mà đọc trả về một danh sách là đối với trường hợp nơi có nhiều phân tích cú pháp hợp lệ. Trường hợp Có thể là trung gian giữa đọc và đọc.
Chris Kuklewicz

Tôi nghĩ điều này yêu cầu Read atypeclass:readMaybe :: Read a => String -> Maybe a
David Tchepak

15

Ngoài quán tính và / hoặc sự thay đổi hiểu biết, một lý do khác có thể là về mặt thẩm mỹ khi có một chức năng có thể hoạt động như một loại nghịch đảo của show. Đó là, bạn muốn đó read . showlà danh tính (đối với các loại là một trường hợp của ShowRead) và đó show . readlà danh tính trên phạm vi của show(tức là show . read . show == show)

Có một Maybetrong các loại readphá vỡ đối xứng với show :: a -> String.


Cảm ơn vì đã thêm một góc mới! Điều đó có lý. Nhưng để đạt được điều đó một cách rõ ràng, sẽ không hợp lý nếu cả hiển thị và đọc đều tạo ra một kiểu riêng biệt, chẳng hạn như "ParsableString"?
Bilal Barakat

1
@BilalBarakat: Loại khác biệt có thể là newtype ValidShow a = ValidShow String. Loại ảo làm cho nó an toàn hơn.
yairchu

9
Đó là một điểm thú vị, nhưng cuối cùng, một sự đối xứng sai. Các lập trình viên nên coi trọng tính đúng đắn hơn tính thẩm mỹ.
Matt Fenwick

1
@yairchu Tôi không hiểu bạn muốn nói gì về loại bóng ma ngay lập tức, vì vậy tôi sẽ làm rõ trong trường hợp bất kỳ ai khác cũng bối rối như tôi. Bạn dự định một cái gì đó giống như showThing :: Show a => a -> ValidShow areadThing :: Read a => ValidShow a -> a, để loại thứ được hiển thị được ghi nhớ trong đối tượng ValidShow. Bằng cách này bạn không thể viết readThing (showThing True) :: String.
amalloy

12

Như @augustss đã chỉ ra, bạn có thể tạo chức năng đọc an toàn của riêng mình. Tuy nhiên, readMaybenó không hoàn toàn phù hợp với read, vì nó không bỏ qua khoảng trắng ở cuối chuỗi. (Tôi đã mắc lỗi này một lần, tôi không nhớ rõ bối cảnh)

Nhìn vào định nghĩa của read trong báo cáo Haskell 98 , chúng ta có thể sửa đổi nó để triển khai một readMaybeđịnh nghĩa hoàn toàn phù hợp readvà điều này không quá bất tiện vì tất cả các chức năng mà nó phụ thuộc đều được định nghĩa trong Prelude:

readMaybe        :: (Read a) => String -> Maybe a
readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                         [x] -> Just x
                         _   -> Nothing

1
Cảm ơn! +1 để cảnh báo tôi về vấn đề khoảng trắng, vấn đề chưa được nêu rõ ràng trước đây.
Bilal Barakat

3
Lưu ý rằng nếu bạn chỉ cần sử dụng safegói, bạn nhận được một phiên bản đúng của readMaybesẵn (nó được gọi readMayvà nó giống với phiên bản này.
Neil Mitchell

8

Chức năng này (được gọi readMaybe) hiện đang ở phần dạo đầu của Haskell! (Tính đến cơ sở hiện tại - 4,6)


2
Chà, văn bản được liên kết cho biết nó nằm trong Text.Read chứ không phải trong Prelude (Có thể đã thay đổi), tuy nhiên, nó vẫn giúp tôi!
Kapichu
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.