Haskell 我能让埃森在多大程度上做举重?

Haskell 我能让埃森在多大程度上做举重?,haskell,jira,aeson,Haskell,Jira,Aeson,我试图避免为toJSON编写定义。这就是我遇到的错误: Datatypes.hs:92:10: No instance for (aeson-0.6.0.2:Data.Aeson.Types.Class.GToJSON (GHC.Generics.Rep (HashMap Key Project))) arising from a use of `aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmt

我试图避免为toJSON编写定义。这就是我遇到的错误:

Datatypes.hs:92:10:
    No instance for (aeson-0.6.0.2:Data.Aeson.Types.Class.GToJSON
                       (GHC.Generics.Rep (HashMap Key Project)))
      arising from a use of `aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON'
Possible fix:
  add an instance declaration for
  (aeson-0.6.0.2:Data.Aeson.Types.Class.GToJSON
     (GHC.Generics.Rep (HashMap Key Project)))
In the expression:
  (aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON)
In an equation for `toJSON':
    toJSON = (aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON)
In the instance declaration for `ToJSON (HashMap Key Project)'
我的所有HashMap
数据
声明都会出现类似的错误

这是相关代码。如果缺少信息,请告诉我

{-# LANGUAGE DeriveGeneric #-}  -- for JTask and Fields ToJSON instances:w!
{-# LANGUAGE DeriveDataTypeable #-} -- This may be needed for HashMaps
{-# LANGUAGE FlexibleInstances #-} -- for the HashMap ToJSON instances
{-# LANGUAGE DefaultSignatures #-}

import Prelude
import Data.ByteString
import GHC.Generics (Generic )
import Data.Data 
import Data.Typeable (Typeable) -- fix HashMap ToJSON instances? maybe
import Data.Aeson
import Data.Aeson.Generic  
import Data.Aeson.Types -- (ToJSON,FromJSON)
import Data.HashMap.Strict (HashMap)

data JTask = JTask {fields :: Fields} deriving (Typeable,Data,Generic)
data Fields = Fields { project :: HashMap Key Project
                     , summary :: ByteString
                     , issuetype :: HashMap Name Task
                     , versions :: [HashMap Name Version]
                     , description :: ByteString
                     } deriving (Typeable,Data,Generic)

data Key = Key deriving (Typeable,Data,Generic)
instance Show Key where
   show Key = "key"

data Name = Name deriving (Typeable,Data,Generic)
instance Show Name where
   show Name = "name"

data Task = Task deriving (Typeable,Data,Generic)

type Version = ByteString -- Placeholder type. Probably using Day for realsies.

data Project = BNAP deriving (Typeable,Data,Generic) -- Fill this out as we go 

instance Generic (HashMap Key Project)
instance Data (HashMap Key Project)
--instance GToJSON (HashMap Key Project)

instance Generic (HashMap Name ByteString)
instance Data (HashMap Name ByteString)

instance Generic (HashMap Name Task)
instance Data (HashMap Name Task)
-- JSON instances
instance ToJSON CreateError
instance ToJSON Fields
instance ToJSON JTask 

instance ToJSON Key
instance ToJSON Name
instance ToJSON Task
instance ToJSON Project

instance ToJSON (HashMap Key Project)
instance ToJSON (HashMap Name Task)
instance ToJSON (HashMap Name ByteString)
-- instance ToJSON Version uncomment when we change Version's type.
我无法为
Data.Aeson.Types.Class.GToJSON创建实例,因为
Data.Aeson.Types.Class
未导出。我有什么选择?我需要手工写什么?
deriveJSON
是最佳选择吗

更新: 我实施了下面的建议。 这是密码

createObject :: CreateConf -> ResourceT IO Value
createObject (CreateConf iSummary iDesc dd) = do
   let jfields = Fields {project = singleton Key BNAP
                        ,summary = iSummary
                        ,issuetype = singleton Name Task
                        ,versions = [singleton Name (calcVersion dd)]
                        ,description = iDesc
                        }
return $ toJSON (JTask jfields)
第一个实例产生
对象fromList[(“key”,Array(fromList[]))]。

第二个实例产生
对象fromList[(“name”,Array(fromList[])]

知道为什么
name
key
是空的吗

我怎么知道

只使用
deriveJSON
会更容易吗

更新: 多亏了NathanHowell的帮助,更重要的问题已经解决了,这就是一元类型的GToJSON实例。解决方案是为一元类型创建自己的实例。JSON对象是无序的,但我不知道这是否重要。如果是这样的话,那么另一个字段的手动ToJSON实例似乎可以解决这个问题

更新:
好的,有点背景。我正在写一个JIRA前端。我提到这一点是因为未来的人们可能会来到这里发现以下好消息:JIRA不关心对象顺序。

Aeson为
HashMap String a
提供了一个
ToJSON
实例。最简单的方法是使用这个实例,将
HashMap
键转换为
Strings
。只需一点样板,它就可以使用
泛型
实例来处理其他所有内容

{-# LANGUAGE DeriveGeneric #-}  -- for JTask and Fields ToJSON instances:w!
{-# LANGUAGE FlexibleInstances #-} -- for the HashMap ToJSON instances
{-# LANGUAGE DefaultSignatures #-}

import Prelude
import Data.ByteString
import GHC.Generics (Generic )
import Data.Aeson
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap

data JTask = JTask {fields :: Fields} deriving (Generic)
data Fields = Fields { project :: HashMap Key Project
                     , summary :: ByteString
                     , issuetype :: HashMap Name Task
                     , versions :: [HashMap Name Version]
                     , description :: ByteString
                     } deriving (Generic)

data Key = Key deriving (Generic)
instance Show Key where
   show Key = "key"

data Name = Name deriving (Generic)
instance Show Name where
   show Name = "name"

data Task = Task deriving (Generic)

type Version = ByteString -- Placeholder type. Probably using Day for realsies.

data Project = BNAP deriving (Generic) -- Fill this out as we go 

instance ToJSON Fields
instance ToJSON JTask 

instance ToJSON Key
instance ToJSON Name
instance ToJSON Task
instance ToJSON Project

mapfst :: (a -> b) -> [(a, v)] -> [(b, v)]
mapfst f = fmap $ \ (k, v) -> (f k, v)

instance ToJSON a => ToJSON (HashMap Key a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList

instance ToJSON a => ToJSON (HashMap Name a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList

Aeson为
HashMap字符串a
提供了一个
ToJSON
实例。最简单的方法是使用这个实例,将
HashMap
键转换为
Strings
。只需一点样板,它就可以使用
泛型
实例来处理其他所有内容

{-# LANGUAGE DeriveGeneric #-}  -- for JTask and Fields ToJSON instances:w!
{-# LANGUAGE FlexibleInstances #-} -- for the HashMap ToJSON instances
{-# LANGUAGE DefaultSignatures #-}

import Prelude
import Data.ByteString
import GHC.Generics (Generic )
import Data.Aeson
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap

data JTask = JTask {fields :: Fields} deriving (Generic)
data Fields = Fields { project :: HashMap Key Project
                     , summary :: ByteString
                     , issuetype :: HashMap Name Task
                     , versions :: [HashMap Name Version]
                     , description :: ByteString
                     } deriving (Generic)

data Key = Key deriving (Generic)
instance Show Key where
   show Key = "key"

data Name = Name deriving (Generic)
instance Show Name where
   show Name = "name"

data Task = Task deriving (Generic)

type Version = ByteString -- Placeholder type. Probably using Day for realsies.

data Project = BNAP deriving (Generic) -- Fill this out as we go 

instance ToJSON Fields
instance ToJSON JTask 

instance ToJSON Key
instance ToJSON Name
instance ToJSON Task
instance ToJSON Project

mapfst :: (a -> b) -> [(a, v)] -> [(b, v)]
mapfst f = fmap $ \ (k, v) -> (f k, v)

instance ToJSON a => ToJSON (HashMap Key a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList

instance ToJSON a => ToJSON (HashMap Name a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList

(aeson-0.6.0.2:Data.aeson.Types.Class.GToJSON
GToJSON
不导出,因为它们不打算由最终用户实现。这是使用
GHC.Generics
派生typeclass实例的常见模式。这是用于Yesod应用程序的。我已经导入了Yesod json。这是在aeson和json之间选择的问题吗YesSOD json?如果我需要使用YesSOD json,我还可以如何创建ToJSON实例呢?
YesSOD json
似乎使用
aeson
进行实际的json转换。我们使用的是
aeson
的补丁版本,我不知道它是否会改变行为……试试我的小测试应用程序:
没有实例(aeson-0.6.0.2:Data.aeson.Types.Class.GToJSON
GToJSON
不导出,因为它们不打算由最终用户实现。这是使用
GHC.Generics
派生typeclass实例的常见模式。这是用于Yesod应用程序的。我已经导入了Yesod json。这是在aeson和json之间选择的问题吗YesSOD json?如果我需要使用YesSOD json,我还可以如何创建ToJSON实例?
YesSOD json
似乎使用
aeson
进行实际的json转换。我们确实使用了
aeson
的补丁版本,我不知道它是否会改变行为……试试我的小测试应用程序: