Использование readMaybe для чтения списка натуральных чисел

Я использую эту функцию для чтения списка натуральных чисел из строки в следующем формате: [1, 2, 3]:

readMaybeIntList :: String -> Maybe [Int]
readMaybeIntList line = case readMaybe line of
                          Just l -> return l
                          Nothing -> Nothing

Сейчас это работает только для целых чисел — как правильно проверить, являются ли числа натуральными? Должен ли я изменить предложение Just l, чтобы проверить, все ли числа равны >=0? Стоит ли возвращать Nothing из такого вложенного предложения Just?


person syntagma    schedule 28.05.2017    source источник
comment
не очень интересный ответ, но я бы сказал да на оба вопроса, которые вы подняли   -  person hao    schedule 29.05.2017
comment
Вы можете использовать что-то вроде Just l | all (>=0) l -> ...   -  person chi    schedule 29.05.2017
comment
Ваш оператор case эквивалентен только readMaybe line точно так же, как if b then true else false эквивалентен только b.   -  person Rein Henrichs    schedule 29.05.2017
comment
Я знаю об этом, просто вставил этот код, так как я думаю, что его следует изменить таким образом (используя case).   -  person syntagma    schedule 29.05.2017


Ответы (2)


Что ж, если вы все равно собираетесь использовать return для вызова экземпляра монады для Maybe, то я, пожалуй, напишу:

import Text.Read
import Control.Monad

readMaybeNatList :: String -> Maybe [Int]
readMaybeNatList line = do
  ns <- readMaybe line
  guard $ all (>=0) ns
  return ns

что является более идиоматичным применением монады Maybe. Является ли это более ясным, чем альтернатива с явным сопоставлением с образцом (и без монад):

readMaybeNatList' :: String -> Maybe [Int]
readMaybeNatList' line =
  case readMaybe line of
    Just ns | all (>=0) ns -> Just ns
    _ -> Nothing

вероятно, вопрос мнения и целевой аудитории.

person K. A. Buhr    schedule 28.05.2017

Вы можете использовать do-обозначение и guard из Control.Monad, чтобы избежать чрезмерного сопоставления с образцом:

import Text.Read
import Control.Monad


readMaybeNatural :: String -> Maybe Int
readMaybeNatural str = do
  n <- readMaybe str
  guard $ n >= 0
  return n


readMaybeNaturals :: String -> Maybe [Int]
readMaybeNaturals =
  sequence . map readMaybeNatural . words
person Anler    schedule 28.05.2017
comment
Кроме того, sequence . map f = traverse f - person Jon Purdy; 29.05.2017