#haskell
#хаскелл
Вопрос:
Приведенный ниже код включает в себя использование 2 монад, и каким-то образом мне нужно накручивать и переносить фактические данные через типы read_field
.
Что я хотел бы сделать, так это иметь возможность извлекать строку из результирующей монады (если все в порядке), а затем передавать ее в get_field
, затем, когда она выйдет, оберните ее в результат и отправьте в main либо для печати, либо для исправления ошибок.
module Main where
import System.IO
import System.Environment
import Text.Printf
import Text.JSON.Generic
import Text.JSON.Types
import Text.JSON
touchJSONfile path = do
-- Touches a file into existence. The good touch.
writeFile path "{}n"
return ()
read_field :: String -> String -> IO String
read_field filename key = do
result <- readFile filename
let json_data = decode result :: Result JSValue
value <- json_data >>= x -> get_field x key -- right here
return (value)
main :: IO ()
main = do
args <- getArgs
case head args of
"init-store" -> touchJSONfile (args !! 1)
"set-keyf" -> putStrLn $ show args --stub
"set-keyi" -> putStrLn $ show args --stub
"get-key" -> putStrLn $ read_field ( args !! 1 ) (args !! 2)
_ -> putStrLn "Error, command not accepted"
return ()
Комментарии:
1.
return ()
In main не нужен; кроме того, вы можете закончитьread_field
простоjson_data >>= ...
; нет необходимости использовать return . В Haskell также принято использовать camelCase, а не подчеркивания.
Ответ №1:
Хорошо, я делаю несколько предположений. Текст в вашем файле json должен быть:
{ "somekeyyousearchfor : "somevalueyouwant" }
В этом случае давайте сделаем это шаг за шагом. Сначала у нас есть результат:
read_field filename key = do
result <- readFile filename
let res = decode result :: Result JSValue
Результат либо Ok JsValue, либо строка ошибки, поэтому:
read_field filename key = do
result <- readFile filename
let json_data = decode result :: Result JSValue
return $ case res of
Error e -> ""
Ok json_data -> undefined
Пока все хорошо. Теперь у нас есть json_data, который является значением JsValue. Входные данные, которые у нас есть, — это объект, поэтому:
read_field filename key = do
result <- readFile filename
let json_data = decode result :: Result JSValue
return $ case res of
Error e -> ""
Ok json_data -> case json_data of
JSObject ob -> undefined
_ -> ""
Хорошо, теперь у нас есть JSObject, где ob — JsValue JSObject . Этот JSObject является новым типом, а не конструктором, как предыдущий, но может использовать для него функцию get_field, поэтому:
read_field filename key = do
result <- readFile filename
let json_data = decode result :: Result JSValue
return $ case res of
Error e -> ""
Ok json_data -> case json_data of
JSObject ob -> case (get_field ob key) of
Just (JSString str) -> ""
_ -> ""
_ -> ""
Он вернул только JsValue , и поскольку мы предполагаем, что это будет строка, нас не волнуют никакие другие значения. Итак, это JSString, который является оболочкой вокруг обычной строки, поэтому:
read_field :: String -> String -> IO String
read_field filename key = do
result <- readFile filename
let res = decode result :: Result JSValue
return $ case res of
Error e -> ""
Ok json_data ->
case json_data of
JSObject ob -> case (get_field ob key) of
Just (JSString str) -> fromJSString str
_ -> ""
_ -> ""
Немного раздражает, но есть другая библиотека под названием aeson, которая делает все совсем по-другому, и она немного более компактна, но и немного сложнее. В списке haskell-beginners, который я недавно опубликовал, есть хороший пример того, как его использовать.
Ответ №2:
Попробуйте что-то вроде этого:
read_field :: String -> String -> IO String
read_field filename key = do
result <- readFile filename
case decode result of
OK value -> get_field value key
Error err -> error err -- Do something with the error case; for now, kill the program.