通常我知道如何修复不明确的类型变量问题,但这次我不知道了。长话短说,我使用protobuf Haskell库来处理协议缓冲区。该库使您忘记了单独维护。proto文件,如果数据类型分别是Encode和Decode类型类的实例,则派生序列化和反序列化数据类型的方法。
我正在protobuf之上设计一个简单的协议。有一个主消息数据类型,包含消息id、消息类型和一些取决于类型的可选数据。我想有一个函数来获取消息id、消息类型和可选数据(需要是Encode类的实例),并创建一个新的MyMessage实例,其中可选数据提前序列化为ByteString。
我就是这样做的:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
import Data.ByteString (ByteString)
import Data.Int
import Data.Maybe
import Data.Monoid
import Data.ProtocolBuffers
import Data.Serialize
import Data.Text (Text, pack)
import GHC.Generics (Generic)
import GHC.TypeLits
data MyMsgType = MSG_TYPE_1
| MSG_TYPE_2
deriving (Enum, Show)
data MyMessage = MyMessage {
msgId :: Required 1 (Value Int64)
, msgType :: Required 2 (Enumeration MyMsgType)
, cpData :: Optional 3 (Value ByteString)
} deriving (Generic, Show)
instance Encode MyMessage
instance Decode MyMessage
createMessage :: Encode a => Int64 -> MyMsgType -> Maybe a -> MyMessage
createMessage msgId msgType optionalData =
MyMessage (putField msgId) (putField msgType) (putField $ serialiseOptionalData optionalData)
serialiseMessage :: MyMessage -> ByteString
serialiseMessage = runPut . encodeLengthPrefixedMessage
serialiseOptionalData :: Encode a => Maybe a -> Maybe ByteString
serialiseOptionalData Nothing = Nothing
serialiseOptionalData (Just ctx) =
Just . runPut . encodeLengthPrefixedMessage $ ctx
尝试使用createMessage函数时,出现以下错误:
λ> createMessage 1 MSG_TYPE_1 Nothing
<interactive>:7:1:
No instance for (Encode a0) arising from a use of ‘createMessage’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Encode MyMessage -- Defined at test.hs:24:10
instance Encode
(unordered-containers-0.2.6.0:Data.HashMap.Base.HashMap
protobuf-0.2.1.0:Data.ProtocolBuffers.Wire.Tag
[protobuf-0.2.1.0:Data.ProtocolBuffers.Wire.WireField])
-- Defined in ‘protobuf-0.2.1.0:Data.ProtocolBuffers.Encode’
In the expression: createMessage 1 MSG_TYPE_1 Nothing
In an equation for ‘it’: it = createMessage 1 MSG_TYPE_1 Nothing
有人能解释一下为什么会出现这个错误以及如何修复它吗?我不知道编译器究竟在哪里看到了歧义。
您需要提供有关可选数据类型的更多信息。当您使用Nothing(无)作为类型a的值时,编译器无法推断a的确切类型。您可以通过显式地将类型指定给Nothing来修复它,如在(Nothing::Maybe Foo)
中。
以下代码是递归变量函数重载的教科书示例。在clang和GCC中,它编译干净,返回36(如预期的那样): 然而,这里有一个小小的修改。它在模板定义中使用依赖类型,而不是直接使用模板参数: 它使用GCC 5.2编译并运行,但使用clang 3.8时失败: 我的问题是双重的。 是否真的有效使用参数包 typename 模式将范围解析运算符应用于包的每个成员,如 ? clang 相对于标准是否正确,或者这
但是,当我尝试相同的示例时,通过将Integer更改为Object,代码编译得很好,输出为String 谁能帮助我理解为什么当输出来自其中有字符串的方法时,签名中有对象的方法是必需的。以及类型错误不明确的原因是什么。
我有一节简单的课 这将输出为10,没有任何错误!!!我原以为这会给我一个ClassCastException,其中有些错误,比如Integer不能转换为HashMap。 出于好奇和愤怒,我尝试了返回值,如下所示
无法找出正确的方法来使用匹配器来识别我要处理的exchange方法的重载。我正在打的电话:
问题内容: 如果在调用时没有设置信号挂起,则线程将被挂起,直到一个或多个挂起。set定义的信号在调用sigwait()时应已被阻止;否则,行为是不确定的。sigwait()对set中的信号的信号动作的影响未指定。 这真的很模棱两可,和这里有什么区别? 而其对如何进行选择的结论并不能完全清楚: 总之,当需要运行代码以响应异步信号来通知线程时,应使用sigwait()处理该信号。或者,如果实现提供信号
我应该如何编写以下Mockito匹配器,以便调用不会有歧义? 我试图在代码中模拟的实际函数调用是: