เหตุใด Prelude.read ของ Haskell จึงไม่ส่งคืนอาจจะ?


109

มีเหตุผลที่ดีหรือไม่ที่ประเภทของ Prelude.read คือ

read :: Read a => String -> a

แทนที่จะคืนMaybeค่า?

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

เนื่องจากสตริงอาจไม่สามารถแยกวิเคราะห์ได้ Haskell จึงจะไม่เป็นธรรมชาติมากกว่านี้หรือ?

หรือแม้แต่สตริงเดิมจะมีสตริงเดิมEither String aอยู่ที่ไหนLeftหากไม่ได้แยกวิเคราะห์และRightผลลัพธ์จะเป็นอย่างไร

แก้ไข:

ฉันไม่ได้พยายามให้คนอื่นเขียนกระดาษห่อหุ้มที่เกี่ยวข้องให้ฉัน เพียงแค่ขอความมั่นใจว่าทำได้อย่างปลอดภัย


14
ทำไมไม่takeยอมรับใด ๆNum a => a? เหตุใดจึงมีกรณีพิเศษfmapสำหรับรายการ เหตุใดจึงFunctorไม่จำเป็นสำหรับMonadอินสแตนซ์ ฉันคาดว่าคำตอบจะคล้ายกับคำตอบของคำถามเหล่านี้และคำถามที่เกี่ยวข้อง

3
นั่นเป็นเหตุผลว่าทำไมฉันถึงใช้คำนี้ในแบบที่ฉันทำโดยปล่อยให้ตัวเลือกนั้นเปิดอยู่โดยไม่มีเหตุผลที่ดี ในขณะที่ฉันยังสงสัยว่าอาจไม่มีเช่นตัวอย่างที่คุณให้มา แต่ก็คุ้มค่าที่จะขอให้แน่ใจว่าการเขียนกระดาษห่อหุ้มของตัวเองจะไม่สร้างปัญหาที่ไม่คาดฝันที่ปลายน้ำ
Bilal Barakat

ฉันหวังว่าreadMaybeจะมีการเพิ่มฟังก์ชันในเร็ว ๆ นี้
ส.ค.

จุดดี @delnan แต่ไม่ควรtakeจะเป็นIntegral n => n -> [a] -> [a]?
Doug McClean

@DougMcClean: ใช่มันควรจะเป็นจริงIntegralไม่ใช่Num- สมองผายลม

คำตอบ:


108

แก้ไข : ใน GHC 7.6 readMaybeมีอยู่ในText.Readโมดูลในแพ็คเกจพื้นฐานพร้อมกับreadEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


คำถามดีมาก! ประเภทของการอ่านจะไม่เปลี่ยนแปลงในเร็ว ๆ นี้เพราะจะทำให้หลายสิ่งหลายอย่างพังทลาย อย่างไรก็ตามควรมีmaybeReadฟังก์ชั่น

ทำไมไม่มี? คำตอบคือ "ความเฉื่อย" มีการอภิปรายในปี '08ซึ่งตกรางจากการอภิปรายเรื่อง "ล้มเหลว"

ข่าวดีก็คือผู้คนมีความเชื่อมั่นเพียงพอที่จะเริ่มถอยห่างจากความล้มเหลวในห้องสมุด ข่าวร้ายคือข้อเสนอหายไปในการสับเปลี่ยน มีควรจะเป็นฟังก์ชั่นดังกล่าวถึงแม้คนหนึ่งจะง่ายต่อการเขียน (และมี zillions รุ่นที่คล้ายกันมากลอย codebases รอบ ๆ อีกมากมาย)

ดูการสนทนานี้ด้วย

ส่วนตัวผมใช้รุ่นจากแพคเกจความปลอดภัย


30

ใช่มันจะสะดวกกับฟังก์ชั่นการอ่านที่ส่งคืนอาจจะ คุณสามารถสร้างเองได้:

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

3
ขอบคุณ! ฉันหวังว่าการแก้ไขจะไม่ฟังดูเนรคุณ! :) แค่อยากจะบอกให้ชัดเจนฉันไม่ได้ถามด้วยความขี้เกียจ ...
Bilal Barakat

6
หาก @augustss ไม่สามารถให้คำตอบที่ดีกว่าอาจไม่มีอยู่
John L

2
ฉันไม่คิดว่าอาจจะเคยมีการพูดถึงเวอร์ชันเดิมในการออกแบบดั้งเดิม หลายสิ่งเหล่านี้เห็นได้ชัดเมื่อมีประสบการณ์ แต่คาดเดาได้ยาก
ส.ค.

เหตุผลที่อ่านผลตอบแทนรายการสำหรับกรณีที่มีหลายแยกวิเคราะห์ที่ถูกต้อง กรณีอาจจะอยู่ระหว่างการอ่านและการอ่าน
Chris Kuklewicz

ฉันคิดว่านี่ต้องใช้Read aคลาสประเภท:readMaybe :: Read a => String -> Maybe a
David Tchepak

15

นอกเหนือจากความเฉื่อยและ / หรือการเปลี่ยนแปลงข้อมูลเชิงลึกแล้วอีกสาเหตุหนึ่งอาจเป็นเพราะการมีฟังก์ชันที่สามารถทำหน้าที่ผกผันshowได้อย่างสวยงาม นั่นคือคุณต้องการให้นั่นread . showคือเอกลักษณ์ (สำหรับประเภทที่เป็นอินสแตนซ์ของShowและRead) และนั่นshow . readคือข้อมูลประจำตัวในช่วงของshow(เช่นshow . read . show == show)

มีMaybeในรูปแบบของการแบ่งสัดส่วนด้วยreadshow :: a -> String


ขอบคุณที่เพิ่มมุมมองใหม่! ที่สมเหตุสมผล แต่เพื่อให้บรรลุผลสำเร็จนั้นจะไม่สมเหตุสมผลที่จะให้ทั้งการแสดงและการอ่านสร้างประเภทที่แตกต่างกันให้พูดว่า "ParseableString"?
Bilal Barakat

1
@BilalBarakat: newtype ValidShow a = ValidShow Stringประเภทที่แตกต่างกันอาจจะเป็น ประเภท Phantom ทำให้ประเภทปลอดภัยมากขึ้น
yairchu

9
เป็นจุดที่น่าสนใจ แต่ท้ายที่สุดแล้วความสมมาตรที่ผิดพลาด โปรแกรมเมอร์ควรให้ความสำคัญกับความถูกต้องมากกว่าสุนทรียภาพ
Matt Fenwick

1
@yairchu มันไม่ชัดเจนสำหรับฉันในทันทีว่าคุณหมายถึงอะไรเกี่ยวกับประเภทผีดังนั้นฉันจะชี้แจงในกรณีที่มีใครสับสนเหมือนฉัน คุณตั้งใจบางอย่างshowThing :: Show a => a -> ValidShow aและreadThing :: Read a => ValidShow a -> aเพื่อให้จำประเภทของสิ่งที่แสดงไว้ในออบเจ็กต์ ValidShow วิธีนี้คุณไม่สามารถเขียนreadThing (showThing True) :: Stringได้
amalloy

12

ดังที่ @augustss ชี้ให้เห็นคุณสามารถสร้างฟังก์ชันการอ่านที่ปลอดภัยของคุณเองได้ อย่างไรก็ตามเขาreadMaybeไม่สอดคล้องกับการอ่านอย่างสมบูรณ์เนื่องจากไม่ได้เพิกเฉยต่อช่องว่างที่ท้ายสตริง (ฉันทำผิดครั้งนี้ฉันจำบริบทไม่ค่อยได้)

เมื่อพิจารณาถึงคำจำกัดความของการอ่านในรายงาน Haskell 98เราสามารถปรับเปลี่ยนเพื่อใช้งานreadMaybeที่สอดคล้องกันได้อย่างสมบูรณ์readและสิ่งนี้ไม่สะดวกเกินไปเนื่องจากฟังก์ชันทั้งหมดที่ขึ้นอยู่นั้นได้กำหนดไว้ใน Prelude:

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

1
ขอบคุณ! +1 เพื่อแจ้งเตือนฉันเกี่ยวกับปัญหาช่องว่างซึ่งไม่เคยมีการระบุไว้อย่างชัดเจนมาก่อน
Bilal Barakat

3
โปรดทราบว่าหากคุณใช้safeแพ็กเกจคุณจะได้รับเวอร์ชันที่ถูกต้องreadMaybe(เรียกreadMayและเหมือนกับเวอร์ชันนี้
Neil Mitchell

8

ฟังก์ชั่นนี้ (เรียกว่าreadMaybe) อยู่ในช่วงโหมโรงของ Haskell แล้ว! (ณ ฐานปัจจุบัน - 4.6)


2
ข้อความที่เชื่อมโยงบอกว่าอยู่ใน Text อย่างไรก็ตามอ่านแล้วไม่ใช่ใน Prelude (อาจมีการเปลี่ยนแปลง) แต่ก็ยังช่วยฉันได้!
Kapichu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.