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

基本的に、JSON 文字列を何としてデコードしたいかを aeson のデコードに伝える必要があります。

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

Aeson にインスタンスを生成させたい場合は、コンパイルで拡張機能 DerivGenerics を有効にしてください。

行に注釈を追加する必要があります

変化する

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 に答える