1

我正在编写一个小程序来解析来自 TCP 连接的 JSON,但我遇到了一个错误:

Main.hs:43:22:
    No instance for (FromJSON t0) arising from a use of `decode'
    The type variable `t0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there is a potential instance available:
      instance FromJSON LogIn -- Defined at Main.hs:21:10
    In the expression: decode lazyLine
    In a pattern binding: Just login = decode lazyLine
    In the expression:
      do { line <- BS.hGetLine handle;
           let lazyLine = BL.fromChunks ...;
           let Just login = decode lazyLine;
           hPutStrLn handle ".";
           .... }

我不知道要添加什么签名instance FromJSON LogIn

代码是:

{-# LANGUAGE DeriveGeneric #-}

module Main(main) where

import Network (listenOn, withSocketsDo, accept, PortID(..), Socket)
import System (getArgs)
import System.IO (hSetBuffering, hPutStrLn, BufferMode(..), Handle)
import Control.Concurrent (forkIO)
import qualified Data.ByteString as BS

import Data.Text
import Data.Aeson
import GHC.Generics
import qualified Data.ByteString.Lazy as BL

data LogIn = LogIn
  { username :: String
  , password :: String
  } deriving (Show, Generic)

instance FromJSON LogIn

main :: IO ()
main = withSocketsDo $ do
    sock <- listenOn $ PortNumber 3333
    putStrLn $ "Listening on " ++ "3333"
    sockHandler sock


sockHandler :: Socket -> IO ()
sockHandler sock = do
    (handle, _, _) <- accept sock
    hSetBuffering handle NoBuffering
    forkIO $ commandProcessor handle
    sockHandler sock


commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- BS.hGetLine handle
    let lazyLine = BL.fromChunks [line]
    let Just login = decode lazyLine
    hPutStrLn handle "." --(show login)
    commandProcessor handle
4

2 回答 2

5

这将编译:

commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- BS.hGetLine handle
    let lazyLine = BL.fromChunks [line]
    let Just login = decode lazyLine :: Maybe LogIn
    hPutStrLn handle "." --(show login)
    commandProcessor handle

基本上,您需要告诉 aeson 的 decode 您想要将 JSON 字符串解码为什么。

let Just login = decode lazyLine :: Maybe LogIn
于 2014-06-18T20:36:44.957 回答
1

如果您想让 Aeson 为您生成实例,请确保在编译中打开扩展 DeriveGenerics

您需要在该行中添加注释

改变

let Just login = decode lazyLine 

let Just login = decode lazyLine :: Maybe LogIn

否则,您可以手动编写实例。

您需要为已实现的类型提供一个类型类FromJSON LogIn实例parseJSON

喜欢:

http://hackage.haskell.org/package/aeson-0.6.1.0/docs/Data-Aeson.html#t:FromJSON

{-# LANGUAGE OverloadedStrings #-}

instance FromJSON Coord where
   parseJSON (Object ob) = LogIn            <$>
                           ob .: "username" <*>
                           ob .: "password"

   parseJSON _          = mzero
于 2014-06-18T20:18:18.203 回答