如何使用Text.JSON提取数据?

时间:2016-07-08 12:01:09

标签: json haskell io

我试图围绕ffprobe编写一个包装器,以value格式提取{J}格式{"format": {"format_name": value}}。 JSON由创建的进程输出。这就是我所得到的。

import System.Process
import System.Environment
import System.IO
import Text.JSON

main = do
    args <- getArgs
    (_, Just out, _, p) <- createProcess
        (proc "ffprobe" [args!!0, "-of", "json", "-show_format"])
        { std_out = CreatePipe }
    s <- hGetContents out
    --putStrLn $ show (decode s :: Result JSValue)
    --waitForProcess p
    --putStrLn $ valFromObj "format_name" format
    --    where format = valFromObj "format" rootObj
    --          (Ok rootObj) = decode s :: Result (JSObject (JSValue))
    let (Ok rootObj) = decode s :: Result (JSObject (JSValue))
    let (Ok format) = valFromObj "format" rootObj :: Result (JSObject (JSValue))
    putStrLn format_name
        where (Ok format_name) = valFromObj "format_name" format

无法编译:

[1 of 1] Compiling Main             ( ffprobe.hs, ffprobe.o )

ffprobe.hs:20:59: error:
    Variable not in scope: format :: JSObject JSValue

我对几件事情感到困惑,包括为什么我无法获得编译的最后一行:

  1. 为什么我无法在Ok之后的Result中声明::。像:: Result Ok JSObject JSValue

  2. 为什么我不能在where子句中提取值?

  3. 为什么Result (JSObject (JSValue))而不是Result JSObject JSValue

  4. 为什么format超出范围?

  5. 我有一种感觉,我将IO和Result monad混合在同一个do块中。 Result甚至是monad吗?我是否可以在单独的do中提取我想要的值,而无需遍历IO do

2 个答案:

答案 0 :(得分:2)

我认为你的编译错误是因为where的位置。尝试

main = do
    ...
    let (Ok format) = valFromObj "format" rootObj :: Result (JSObject (JSValue))
    let (Ok format_name) = valFromObj "format_name" format
    putStrLn format_name

where的范围超出了do,所以它不了解format

答案 1 :(得分:1)

你不能这样做:

main = do
  let bar = "only visible inside main? "
  return baz
  where
    baz = bar ++ " yes, this will break!"

这给出了:

test.hs:7:11:
    Not in scope: ‘bar’
    Perhaps you meant ‘baz’ (line 7)

让绑定不同于函数参数在绑定的位置不可用。 bar以上的baz不在Update-Database –TargetMigration: m1 范围内。与您的代码比较。