2014-11-02 116 views
1

假設你有一個簡單的類型,並且想用Aeson將它序列化爲JSON。以下是基本設置:如何在Haskell中將參數化類型序列化爲JSON?

{-# LANGUAGE DeriveGeneriC#-} 

import Data.Aeson (ToJSON) 
import Data.Aeson (encode) 
import GHC.Generics 

data Spotting = Spotting { 
    state :: String, 
    bird :: String 
} deriving (Show, Generic) 

instance ToJSON Spotting 

現在說你想要的,除了birdstate領域,允許用戶在加時賽/自定義元數據傳遞。對於鳥類發現,也許這是氣溫,鳥類的密度,潮汐的位置......可能是任何事情,我們事先不知道。

從看着像Twitter API in Haskell的例子,它看起來像你想構建這樣的:

data Spotting meta = Spotting { 
    state :: String, 
    bird :: String, 
    meta :: meta 
} deriving (Show, Generic) 

instance ToJSON meta => ToJSON (Spotting meta) 

從我的理解,到目前爲止,這是一個參數化類型。目標是現在做一個簡單的方法來創建一些JSON。所以我們定義一個這樣的函數:

spotting bird state meta = encode $ Spotting { 
    state = state, 
    bird = bird, 
    meta = meta 
} 

但是我不知道該從哪裏走。當我這樣調用該函數:

record = spotting "Snowy Egret" "California" "low tide" 

它拋出一個錯誤(我是新來的Haskell所以我仍然在學習如何解釋這一切東西的基礎知識)

No instance for (Data.String.IsString meta0) 
    arising from the literal `"low tide"' 
The type variable `meta0' is ambiguous 
Possible fix: add a type signature that fixes these type variable(s) 
Note: there are several potential instances: 
    instance Data.String.IsString 
      aeson-0.7.0.6:Data.Aeson.Types.Internal.Value 
    -- Defined in `aeson-0.7.0.6:Data.Aeson.Types.Internal' 
    instance a ~ Data.ByteString.Internal.ByteString => 
      Data.String.IsString 
      (attoparsec-0.12.1.2:Data.Attoparsec.ByteString.Internal.Parser a) 
    -- Defined in `Data.Attoparsec.ByteString.Char8' 
    instance Data.String.IsString Data.Text.Internal.Text 
    -- Defined in `Data.Text' 
    ...plus five others 
In the third argument of `spotting', namely `"low tide"' 
In the expression: 
    spotting "Snowy Egret" "California" "low tide" 
In an equation for `record': 
    record = spotting "Snowy Egret" "California" "low tide" 

發生了什麼在這裏/你如何得到這個工作?

的最終目標是,不要在meta場傳遞一個字符串,而是一個類型的對象(但它可以是任何對象),像這樣的:

record = spotting "Snowy Egret" "California" MyCustomData { 
    tide = "low" 
} 

你是怎麼做到這一點哈斯克爾?

+0

'可能的修復:添加一個修復這些類型變量的類型簽名' – alternative 2014-11-02 23:20:25

回答

5

的問題是,因爲你有OverloadedStrings開啓....

當你鍵入

record = spotting "Snowy Egret" "California" "low tide" 

編譯器需要確定meta是什麼類型。因爲encode能夠解析許多類型,所以它不能告訴編譯器使用什麼。如果沒有OverloadedStrings,"low tide"顯然是String類型,但有了它,它可能是StringByteString

你有兩個選擇中修復這個....

須─

刪除OverloadedStrings

或-

明確指定類型。

value = "low tide"::String 
record = spotting "Snowy Egret" "California" value