我在SO上看到了这个问题,并试图复制它: Haskell: Reusing FromJSON instances with lenses, lens-aeson, and nested 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变量。我不知道这是从包中导入的东西,还是只是一个任意的变量名,而我滥用了该函数。无论哪种方式,我都不清楚为什么从问题中复制此代码似乎对此失败。
答案 0 :(得分:3)
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或失败使转换失败,例如如果对象缺少必需的键,或者该值的类型错误。
所以在您引用的实例中
instance FromJSON Colour where
parseJSON (String s) = return $ case s of
"blue" -> Blue
"green" -> Green
_ -> Yellow
parseJSON _ = mzero
mzero
表示除String
以外的其他JSON值都不能解释为对Colour
值进行编码。