Используя id внутри нотации do - PullRequest
0 голосов
/ 19 октября 2019

Я смотрю онлайн-курс на Haskell, глава для чтения монада. Инструктор приводит следующий пример: эта функция берет список и возвращает Nothing, если он пустой или (просто head) в противном случае.

safeHead = do
  -- argument is implicit here
  b <- null
  if b then
    return Nothing
  else do
    h <- head
    return $ Just h

safeHead' = do
  e <- id -- the error
  if (null e)
    then Nothing
    else return $ Just (head e)

Вторая функция явно принимает список, используя e <- id. Но, к сожалению, это не работает для меня. ghci выдает ошибку:

• Couldn't match expected type ‘Maybe [a]’
              with actual type ‘a0 -> a0’
 • Probable cause: ‘id’ is applied to too few arguments
    In a stmt of a 'do' block: e <- id
    In the expression:
      do e <- id
         if (null e) then Nothing else return $ Just (head e)

Этот пример, вероятно, был проверен авторами 3 года назад, когда был создан курс (или, возможно, он был неверным с самого начала).

Iесть подозрение, что null принимает обернутое значение, а id нет:

Prelude> :t null
null :: Foldable t => t a -> Bool
Prelude> :t id
id :: a -> a

Что не так и как исправить?

1 Ответ

7 голосов
/ 19 октября 2019

На самом деле, вы просто забыли return. Хорошо работает следующее:

safeHead' = do
  e <- id
  if (null e)
    then return Nothing         -- need return here
    else return $ Just (head e)

или вы можете выделить return out:

safeHead' = do
  e <- id
  return $ if (null e)
    then Nothing
    else Just (head e)
...