如何在Haskell中使用泛型类型的函数

时间:2019-04-20 20:06:47

标签: haskell typeclass monad-transformers

我有一些代码可以从队列中读取数据。我希望该函数能够将回调函数作为参数,而该回调函数基本上包含有关如何处理从队列中提取的数据的代码。

是getMessages功能的类型
getMessages ::  (ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> Kafkamonad (Either Error Result)) -> KafkaMonad (Either Error ())

因此回调函数必须始终为

类型
(ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> Kafkamonad (Either Error Result))

尽管此代码有效,但我希望为get messages函数提供一个更通用的类型,例如

getmessages ::(ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> Kafkamonad a) -> KafkaMonad (Either Error ())
or 
getMessages ::  f -> KafkaMonad (Either Error ())

当我尝试使用提到的类型(例如Kafkamonad a)时,会抛出错误

Couldn't match type ‘a’ with ‘Either Error b0’ ‘a’ is a rigid type variable bound by the type signature for: 
getMessages :: forall a. Callback a -> KafkaMonad a at src/Kafka/Consume.hs:48:17 
Expected type: KafkaMonad (Either KafkaError b0) 
Actual type: KafkaMonad a 

相关功能如下

type Callback a = ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> KafkaMonad a
getMessages ::  Callback a -> KafkaMonad a
getMessages callback = do
       let ....
       runHandler(Right kc)  = processMessages kc callback
    bracket mkConsumer clConsumer runHandler

processMessages :: Kc -> Callback a -> KafkaMonad a
processMessages k callback=     mapM_ (\_ -> do
                    ecr <- pollMessage k (Timeout 1000)
                    case ecr of
                      Right cr ->  do
                                   err <- commitAllOffsets OffsetCommit k
                                   case err of
                                        Nothing  -> callback cr
                                        Just err -> throwIO err 
                      Left err -> return $ Left $ KafkaError "Procesing Stopped"  

            ) [0 :: Integer .. ]
    return $ Right ()

我可以使用哪种类约束来实现此目的?否则任何其他解决方案也将是不错的选择。

1 个答案:

答案 0 :(得分:0)

您可以在Kafkamonad包裹的类型上定义类型别名:

type CallbackType a = ConsumerRecord (Maybe ByteString) (MaybeByteString) -> Kafkamonad a

然后,您也可以使用此类型定义getMesagages

getMessages :: CallbackType a -> KafkaMonad (Either Error ())

请注意,此类型注释指示getMessages的定义是什么;您不能对a可能做任何假设。如果有任何限制(由Kafkamonad施加或由getMessages进行必要的定义),则需要在问题中指定这些限制。

根据您的错误消息,您对Kafkamonad包装的类型有不确定的假设,这会阻止您完全参数化回调类型。试试

type CallbackType a = ConsumerRecord (Maybe ByteString) (MaybeByteString) -> Kafkamonad (Either KafkaError a)

或修改您的定义以删除假设。