我在声明我的类型的 ToJSON
实例(同义词)时遇到问题:
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module Argon.Types (ComplexityBlock, AnalysisResult, ResultsOptions(..)
, OutputMode(..))
where
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as BL
-- | Hold the data associated to a function binding:
-- (line number, column, function name, complexity)
type ComplexityBlock = (Int, Int, String, Int)
instance ToJSON ComplexityBlock where
toJSON (l, c, func, cc) = object [ "lineno" .= l
, "col" .= c
, "name" .= func
, "complexity" .= cc
]
-- | Represent the result of the analysis of one file.
-- It can either be an error message or a list of
-- 'ComplexityBlock's.
type AnalysisResult = Either String [ComplexityBlock]
instance ToJSON (FilePath, AnalysisResult) where
toJSON (p, Left err) = object [ "path" .= p
, "type" .= "error"
, "message" .= err
]
toJSON (p, Right rs) = object [ "path" .= p
, "type" .= "result"
, "blocks" .= rs
]
导入 bytestring 包并启用 OverloadedStrings
扩展后,我认为它可以工作,但事实并非如此:
/home/miki/exp/argon/src/Argon/Types.hs:31:47:
No instance for (ToJSON a0) arising from a use of ‘.=’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance ToJSON (FilePath, AnalysisResult)
-- Defined at src/Argon/Types.hs:29:10
instance ToJSON ComplexityBlock
-- Defined at src/Argon/Types.hs:17:10
In the expression: type .= error
In the first argument of ‘object’, namely
‘[path .= p, type .= error, message .= err]’
In the expression:
object [path .= p, type .= error, message .= err]
/home/miki/exp/argon/src/Argon/Types.hs:31:50:
No instance for (Data.String.IsString a0)
arising from the literal ‘error’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString Value
-- Defined in ‘aeson-0.8.0.2:Data.Aeson.Types.Internal’
instance (a ~ Data.ByteString.Internal.ByteString) =>
Data.String.IsString
(attoparsec-0.12.1.6:Data.Attoparsec.ByteString.Internal.Parser a)
-- Defined in ‘attoparsec-0.12.1.6:Data.Attoparsec.ByteString.Char8’
instance Data.String.IsString
Data.ByteString.Builder.Internal.Builder
-- Defined in ‘Data.ByteString.Builder’
...plus four others
In the second argument of ‘(.=)’, namely ‘error’
In the expression: type .= error
In the first argument of ‘object’, namely
‘[path .= p, type .= error, message .= err]’
/home/miki/exp/argon/src/Argon/Types.hs:35:46:
No instance for (ToJSON a1) arising from a use of ‘.=’
The type variable ‘a1’ is ambiguous
Note: there are several potential instances:
instance ToJSON (FilePath, AnalysisResult)
-- Defined at src/Argon/Types.hs:29:10
instance ToJSON ComplexityBlock
-- Defined at src/Argon/Types.hs:17:10
In the expression: type .= result
In the first argument of ‘object’, namely
‘[path .= p, type .= result, blocks .= rs]’
In the expression:
object [path .= p, type .= result, blocks .= rs]
/home/miki/exp/argon/src/Argon/Types.hs:35:49:
No instance for (Data.String.IsString a1)
arising from the literal ‘result’
The type variable ‘a1’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString Value
-- Defined in ‘aeson-0.8.0.2:Data.Aeson.Types.Internal’
instance (a ~ Data.ByteString.Internal.ByteString) =>
Data.String.IsString
(attoparsec-0.12.1.6:Data.Attoparsec.ByteString.Internal.Parser a)
-- Defined in ‘attoparsec-0.12.1.6:Data.Attoparsec.ByteString.Char8’
instance Data.String.IsString
Data.ByteString.Builder.Internal.Builder
-- Defined in ‘Data.ByteString.Builder’
...plus four others
In the second argument of ‘(.=)’, namely ‘result’
In the expression: type .= result
In the first argument of ‘object’, namely
‘[path .= p, type .= result, blocks .= rs]’
我不明白为什么类型变量是不明确的。
最佳答案
比较签名:
fromString :: IsString a => String -> a
toJSON :: ToJSON a => a -> Value
从技术上讲,要序列化字符串文字,您的自定义实例使用它们的叠加:
toJSON . fromString :: (IsString a, ToJSON a) => String -> Value
请注意类型变量如何从签名中消失,因此出现了歧义。例如,"error"
可以是 String
、Value
或 Text
,所有这些都具有 IsString
和 ToJSON
实例。
一个快速的解决方法是通过提供显式类型签名来手动解决歧义:
toJSON (p, Left err) = object [ "path" .= p
, "type" .= ("error" :: String)
关于haskell - 声明 ToJSON 实例时出现编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33235365/