Что такое mzero в этом примере aeson?

Я видел этот вопрос на SO и пытаюсь его воспроизвести: json">Haskell: повторное использование экземпляров FromJSON с линзами, линзами-эзонами и вложенными JSON

Однако, когда я запускаю то, что, по моему мнению, должно быть полным примером, я получаю сообщение об ошибке.

Вот мой код:

import Data.Aeson
import Data.Aeson.Lens
import Control.Lens
import Data.Aeson.Types

data Colour = Yellow | Green | Blue

instance FromJSON Colour where
  parseJSON (String s) = return $ case s of
        "blue" -> Blue
        "green" -> Green
        _ -> Yellow
  parseJSON _ = mzero

instance ToJSON Colour where
  toJSON Yellow = String "yellow"
  toJSON Blue   = String "blue"
  toJSON Green  = String "green"

parseColour :: String -> Maybe Colour
parseColour j = j ^? key "info" . key "colour" . _JSON

parseColour "{ \"info\": { \"colour\": \"yellow\" } }"

Я получаю это:

 <interactive>:7:17: error: Variable not in scope: mzero :: Parser Colour

Многие поиски показывают успешное использование переменной mzero. Я не могу сказать, это что-то импортированное из пакета или просто произвольное имя переменной, и я неправильно использую функцию. В любом случае, мне непонятно, почему копирование этого кода из вопроса, похоже, не удается.


person Elsie Meow    schedule 12.04.2019    source источник
comment
mzero происходит из класса типов MonadPlus в Control.Monad.   -  person chepner    schedule 12.04.2019
comment
Hoogle подскажет, что импортировать: любой из Control.Monad, Distribution.Compat.Prelude .Internal, Control.Monad.Compat, Protolude, Protolude.Monad, Turtle, ClassyPrelude, RIO, Universum.Monad.Reexport, Rebase.Prelude, LLVM.Prelude,Relude.Monad.Reexport, Stack.Prelude, Yesod.Paginator.Prelude , Control.Monad.Free, OpenSuse.Prelude, Hledger.Web.Import, причем Control.Monad является наиболее распространенным и разумным выбором.   -  person Daniel Wagner    schedule 12.04.2019


Ответы (1)


mzero является частью класса типов MonadPlus, определенного в Control.Monad.

> import Control.Monad
> :info MonadPlus
class (GHC.Base.Alternative m, Monad m) =>
      MonadPlus (m :: * -> *) where
  mzero :: m a
  mplus :: m a -> m a -> m a

Он служит идентификатором для функции mplus, так что mplus mzero x == x и mplux x mzero == x.

Использование mzero в экземплярах FromJSON упоминается в документации:

При записи экземпляра используйте empty, mzero или fail, чтобы сделать преобразование неудачным, например. если в объекте отсутствует требуемый ключ или значение имеет неправильный тип.

Итак, в приведенном вами примере

instance FromJSON Colour where
  parseJSON (String s) = return $ case s of
        "blue" -> Blue
        "green" -> Green
        _ -> Yellow
  parseJSON _ = mzero

mzero указывает, что никакое значение JSON, кроме String, не может интерпретироваться как кодирование значения Colour.

person chepner    schedule 12.04.2019
comment
Есть ли что-нибудь в справке или инструментах hoogle и т. д., что помогло бы мне определить это, не спрашивая? - person Elsie Meow; 12.04.2019