我正在编写一个小程序来解析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
答案 0 :(得分: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解码您要将JSON字符串解码为的内容。
let Just login = decode lazyLine :: Maybe LogIn
答案 1 :(得分: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