Haskell-如何将基于JSON的管道转换为数据记录?

Haskell-如何将基于JSON的管道转换为数据记录?,json,haskell,Json,Haskell,我正在构建一个强化学习库,其中我希望通过管道JSON将某些实例信息传递到可执行文件中 使用aeson的Simplest.hs,我能够让下面的基本示例按预期工作。请注意,参数位于Main.hs中,作为字符串params作为占位符 我试图修改Main.hs,以便通过getContents从JSON文件导入Nim游戏参数,但遇到了预期的[Char]与IO字符串问题。我试图尽可能多地阅读IO,但不知道如何提升JSON解析方法来处理IO 我将如何修改以下内容,以便能够使用JSON中的管道 Main.hs

我正在构建一个强化学习库,其中我希望通过管道JSON将某些实例信息传递到可执行文件中

使用
aeson
Simplest.hs
,我能够让下面的基本示例按预期工作。请注意,参数位于
Main.hs
中,作为
字符串
params
作为占位符

我试图修改
Main.hs
,以便通过
getContents
从JSON文件导入Nim游戏参数,但遇到了预期的
[Char]
IO字符串
问题。我试图尽可能多地阅读IO,但不知道如何提升JSON解析方法来处理IO

我将如何修改以下内容,以便能够使用JSON中的管道

Main.hs

module Main where

import qualified System.Random as Random

import qualified Data.ByteString.Lazy.Char8 as BL

import qualified Games.Engine as Engine
import qualified Games.IO.Nim as NimIO
import qualified Games.Rules.Nim as Nim
import qualified Games.Learn.ValueIteration as VI


main :: IO ()
main = do
    let params = "{\"players\":[\"Bob\", \"Alice\", \"Charlie\"], \"initialPiles\": [3, 4, 5], \"isMisere\": false}"
    let result = NimIO.decode $ BL.pack params :: Maybe NimIO.NimGame
    case result of
        Nothing -> putStrLn "Parameter errors."
        Just game -> do
            putStrLn "Let's play some Nim! Remainder of code omitted"
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Games.IO.Nim 
    ( decode
    , NimGame
    , players
    , initialPiles
    , isMisere
    ) where


import Control.Applicative (empty)
import qualified Data.ByteString.Lazy.Char8 as BL
import Data.Aeson
    ( pairs,
      (.:),
      object,
      FromJSON(parseJSON),
      Value(Object),
      KeyValue((.=)),
      ToJSON(toJSON, toEncoding),
      decode)


data NimGame = NimGame
    { players :: [String]
    , initialPiles :: [Int]
    , isMisere :: Bool
    } deriving (Show)


instance ToJSON NimGame where
    toJSON (NimGame playersV initialPilesV isMisereV) = object [ "players" .= playersV,
                                                                 "initialPiles" .= initialPilesV,
                                                                 "isMisere" .= isMisereV]
    toEncoding NimGame{..} = pairs $
        "players" .= players <>
        "initialPiles" .= initialPiles <>
        "isMisere" .= isMisere


instance FromJSON NimGame where
    parseJSON (Object v) = NimGame <$>
                           v .: "players" <*>
                           v .: "initialPiles" <*>
                           v .: "isMisere"
    parseJSON _          = empty
Games.IO.Nim.hs

module Main where

import qualified System.Random as Random

import qualified Data.ByteString.Lazy.Char8 as BL

import qualified Games.Engine as Engine
import qualified Games.IO.Nim as NimIO
import qualified Games.Rules.Nim as Nim
import qualified Games.Learn.ValueIteration as VI


main :: IO ()
main = do
    let params = "{\"players\":[\"Bob\", \"Alice\", \"Charlie\"], \"initialPiles\": [3, 4, 5], \"isMisere\": false}"
    let result = NimIO.decode $ BL.pack params :: Maybe NimIO.NimGame
    case result of
        Nothing -> putStrLn "Parameter errors."
        Just game -> do
            putStrLn "Let's play some Nim! Remainder of code omitted"
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Games.IO.Nim 
    ( decode
    , NimGame
    , players
    , initialPiles
    , isMisere
    ) where


import Control.Applicative (empty)
import qualified Data.ByteString.Lazy.Char8 as BL
import Data.Aeson
    ( pairs,
      (.:),
      object,
      FromJSON(parseJSON),
      Value(Object),
      KeyValue((.=)),
      ToJSON(toJSON, toEncoding),
      decode)


data NimGame = NimGame
    { players :: [String]
    , initialPiles :: [Int]
    , isMisere :: Bool
    } deriving (Show)


instance ToJSON NimGame where
    toJSON (NimGame playersV initialPilesV isMisereV) = object [ "players" .= playersV,
                                                                 "initialPiles" .= initialPilesV,
                                                                 "isMisere" .= isMisereV]
    toEncoding NimGame{..} = pairs $
        "players" .= players <>
        "initialPiles" .= initialPiles <>
        "isMisere" .= isMisere


instance FromJSON NimGame where
    parseJSON (Object v) = NimGame <$>
                           v .: "players" <*>
                           v .: "initialPiles" <*>
                           v .: "isMisere"
    parseJSON _          = empty
编译错误

module Main where

import qualified System.Random as Random

import qualified Data.ByteString.Lazy.Char8 as BL

import qualified Games.Engine as Engine
import qualified Games.IO.Nim as NimIO
import qualified Games.Rules.Nim as Nim
import qualified Games.Learn.ValueIteration as VI


main :: IO ()
main = do
    --let params = "{\"players\":[\"Bob\", \"Alice\", \"Charlie\"], \"initialPiles\": [3, 4, 5], \"isMisere\": false}"
    let params = getContents
    let result = NimIO.decode $ BL.pack params :: Maybe NimIO.NimGame
    case result of
        Nothing -> putStrLn "Parameter errors."
        Just game -> do
            putStrLn "Let's play some Nim!"
(base) randm@pearljam ~/Projects/gameshs $ stack build
gameshs-0.1.0.0: unregistering (local file changes: app/Nim.hs)
gameshs> configure (lib + exe)
Configuring gameshs-0.1.0.0...
gameshs> build (lib + exe)
Preprocessing library for gameshs-0.1.0.0..
Building library for gameshs-0.1.0.0..
Preprocessing executable 'nim-exe' for gameshs-0.1.0.0..
Building executable 'nim-exe' for gameshs-0.1.0.0..
[2 of 2] Compiling Main

/home/randm/Projects/gameshs/app/Nim.hs:17:41: error:
    • Couldn't match expected type ‘[Char]’
                  with actual type ‘IO String’
    • In the first argument of ‘BL.pack’, namely ‘params’
      In the second argument of ‘($)’, namely ‘BL.pack params’
      In the expression:
          NimIO.decode $ BL.pack params :: Maybe NimIO.NimGame
   |
17 |     let result = NimIO.decode $ BL.pack params :: Maybe NimIO.NimGame
   |                                         ^^^^^^


--  While building package gameshs-0.1.0.0 (scroll up to its section to see the error) using:
      /home/randm/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_mPHDZzAJ_3.2.1.0_ghc-8.10.4 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.2.1.0 build lib:gameshs exe:nim-exe --ghc-options " -fdiagnostics-color=always"
    Process exited with code: ExitFailure 1

getContents
不像您预期的那样返回
String
,而是
IO String
,它是一个“程序”,执行时将生成一个
String
。因此,当您试图用
decode
解析此程序时,当然这不起作用:
decode
解析
字符串
,它无法解析程序

那么,如何执行此程序以获取
字符串
?有两种方法:要么将其作为另一个程序的一部分,要么将其称为
main
,然后它就成为您的入口点


在您的情况下,明智的做法是将
getContent
作为
main
程序的一部分。要做到这一点,请使用左箭头
,如果您的问题涉及某种错误,通常最好发布错误的全文,这样回答您问题的人就不必猜测。添加了替代代码及其生成的编译器错误。这非常有效,谢谢。爱哈斯克尔。。。我已经在Haskell中实现了我的Python库,代码大约是原来的1/4,性能是原来的10倍。