如何将Aeson的解析器与IO结合使用 [英] How to use Parsers from Aeson with IO
问题描述
我具有许多字段的数据类型,如果不是由JSON配置文件手动指定,则应随机设置.我正在使用Aeson解析配置文件.最好的方法是什么?
I have data types with many fields that, if not being manually specified by a JSON configuration file, should be randomly set. I am using Aeson to parse the config file. What is the best way to do this?
当前,我正在将值设置为等于某个不可能的值,然后再检查该值以进行编辑.
Currently, I am setting values equal to some impossible value, and then later checking for said value to edit.
data Example = Example { a :: Int, b :: Int }
default = Example 1 2
instance FromJSON Example where
parseJSON = withObject "Example" $ \v -> Example
<$> (v .: "a" <|> return (a default))
<*> (v .: "b" <|> return (b default))
initExample :: Range -> Example -> IO Example
initExample range (Example x y) = do
a' <- if x == (a default) then randomIO range else return x
b' <- if y == (b default) then randomIO range else return y
return $ Example a' b'
我想要的是类似的东西:
What I would like is something along the lines of:
parseJSON = withObject "Example" $ \v -> Example
<$> (v .: "a" <|> return (randomRIO (1,10))
是否有可能在IO Monad或沿某个随机数生成器的线程中定义解析器,最好使用Aeson?
Is it possible to define Parsers in the IO Monad or thread along some random generator, ideally using Aeson?
推荐答案
好吧,我不知道这是否是个好主意,并且要扩展更大的开发范围,对额外的IO
层进行修改肯定会令人沮丧,但是以下类型检查:
Well, I don't know if it's a good idea, and juggling the extra IO
layer will certainly get frustrating as heck for larger developments, but the following type-checks:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import Data.Aeson
import System.Random
data Example = Example { a :: Int, b :: Int } deriving (Eq, Ord, Read, Show)
instance FromJSON (IO Example) where
parseJSON = withObject "Example" $ \v -> liftA2 Example
<$> ((pure <$> (v .: "a")) <|> pure (randomRIO (3, 4)))
<*> ((pure <$> (v .: "b")) <|> pure (randomRIO (5, 6)))
在后两行中的每行中,第一行pure
为Int -> IO Int
,第二行为IO Int -> Parser (IO Int)
.在ghci中:
In each of the last two lines, the first pure
is Int -> IO Int
, and the second is IO Int -> Parser (IO Int)
. In ghci:
> sequence (decode "{}") :: IO (Maybe Example)
Just (Example {a = 4, b = 6})
这篇关于如何将Aeson的解析器与IO结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!