如何将Aeson的解析器与IO结合使用 [英] How to use Parsers from Aeson with IO

查看:82
本文介绍了如何将Aeson的解析器与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)))

在后两行中的每行中,第一行pureInt -> 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆