1

単純な型があり、それを Aeson で 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

birdここで、 andstateフィールドに加えて、ユーザーが追加/カスタム メタデータを渡すことができるようにしたいとします。野鳥観察の場合、おそらくこれは気温、鳥の密度、潮の位置などです。事前にはわかりませんが、何でもかまいません。

Haskell の Twitter APIのような例を見ると、次のように構成する必要があるように思われます。

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"
}

Haskellでこれをどのように達成しますか?

4

1 に答える 1