Чому Haskell's Prelude.read не повертає "Можливо"?


108

Чи є вагома причина, чому саме тип Prelude.read є

read :: Read a => String -> a

а не повертати Maybeзначення?

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

Оскільки рядок може не бути синтаксичним Haskell, чи не остання буде більш природною?

Або навіть an Either String a, де Leftміститиметься початковий рядок, якби він не розбирав, а Rightрезультат, якби?

Редагувати:

Я не намагаюся змусити інших писати відповідну обгортку для мене. Просто шукаю запевнити, що це безпечно зробити.


14
Чому не takeприймає жодного Num a => a? Чому існує спеціальний випадок fmapдля списків? Чому це Functorне потрібно для Monadекземплярів? Я очікую, що відповідь буде подібною до відповідей на ці та пов’язані з цим питання.

3
Ну, ось чому я сформулював це так, як я це зробив, залишивши варіант відкритим, що немає вагомих причин. Хоча я також підозрюю, що цього не може бути, як, наприклад, з відомих вам прикладів, варто попросити переконатися, що написання власної обгортки не створить непередбачених проблем нижче за течією.
Білал Баракат

Я сподіваюся, що readMaybeфункція буде додана незабаром.
серпень

Хороші бали @delnan, але не повинно takeбути Integral n => n -> [a] -> [a]?
Doug McClean

@DougMcClean: Так, насправді це має бути Integral, а не Num- мозок пердеть.

Відповіді:


106

Редагувати : Станом на GHC 7.6, readMaybeдоступний у Text.Readмодулі в базовому пакеті, а також readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


Чудове запитання! Тип самого читання не змінюється незабаром, оскільки це порушить багато речей. Однак має бути maybeReadфункція.

Чому його немає? Відповідь - "інерція". У 2008 році відбулася дискусія, яка була зірвана дискусією про "провал".

Хороша новина полягає в тому, що люди були достатньо впевнені, щоб почати відходити від невдач у бібліотеках. Погана новина полягає в тому, що пропозиція загубилася в міграції. Там повинна бути такою функція, хоча один легко писати (і є мільярд дуже схожих версії плаваючий навколо багато баз коди).

Дивіться також цю дискусію .

Особисто я використовую версію з безпечного пакету .


30

Так, це було б зручно з функцією читання, яка повертається Можливо. Ви можете зробити його самостійно:

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

3
Дякую! Я сподіваюся, що редагування не звучить невдячно! :) Просто хочу зрозуміти, що я не прошу лінь ...
Білал Баракат

6
Якщо @augustss не може цього надати, кращої відповіді може не існувати.
Джон Л

2
Я не думаю, що, можливо, версія не колись обговорювалася в оригінальному дизайні. Багато з цих речей стають очевидними з досвідом, але їх важко передбачити.
серпень

Причина , яка читає повертає список для випадку , коли є кілька дійсних розбирає. Випадок "Можливо" є проміжним між прочитаними та прочитаними.
Кріс Куклевич

Я думаю, для цього потрібен Read aнабір класів:readMaybe :: Read a => String -> Maybe a
Девід Чепак

15

Крім інертності та / або зміни розуміння, ще однією причиною може бути те, що естетично приємно мати функцію, яка може діяти як своєрідна обернення show. Тобто, ви хочете, щоб read . showце ідентичність (для типів, які є екземпляром Showі Read), і show . readце ідентичність в діапазоні show(тобто show . read . show == show)

Маючи а Maybeтипу readрозриває симетрію с show :: a -> String.


Дякуємо, що додали новий кут! Що має сенс. Але для того, щоб досягти цього чисто, чи не було б сенсом і показ, і читання створювати різний тип, сказати "ParseableString"?
Білал Баракат

1
@BilalBarakat: Виразний тип може бути newtype ValidShow a = ValidShow String. Фантомний тип робить його більш безпечним для типу.
yairchu

9
Це цікавий момент, але, зрештою, хибна симетрія. Програмісти повинні цінувати правильність щодо естетики.
Метт Фенвік

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, і це не дуже незручно, оскільки всі функції, від яких він залежить, визначені в Прелюдії:

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

1
Дякую! +1, щоб попередити мене про проблему пробілу, яка раніше не була чітко викладена.
Білал Баракат

3
Зауважте, що якщо ви просто використовуєте safeпакет, ви отримаєте правильну readMaybeдоступну версію (вона називається readMayі вона ідентична цій версії.
Neil Mitchell

8

Ця функція (називається readMaybe) тепер є прелюдією Haskell! (Станом на поточну базу - 4,6)


2
Ну, зв'язаний текст говорить, що це в Text.Read, а не в Prelude (можливо, змінилися), однак, це все-таки мені допомогло!
Капічу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.