Как использовать универсальный тип для функций в haskell - PullRequest
0 голосов
/ 20 апреля 2019

У меня есть код, который читает данные из очереди.Я хочу, чтобы функция была такой, чтобы она принимала функцию обратного вызова в качестве параметра, функция обратного вызова в основном содержит код того, что делать с данными, извлеченными из очереди.Тип для функции getMessages выглядит примерно так:

getMessages ::  (ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> Kafkamonad (Either Error Result)) -> KafkaMonad (Either Error ())

, поэтому функция обратного вызова всегда должна иметь тип

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

, хотя этот код работает, и я хотел бы иметь более общийтип для функции получения сообщений, что-то вроде

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

Когда я пытаюсь использовать упомянутые типы, например Kafkamonad, он выдает ошибку

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 голосов
/ 21 апреля 2019

Вы можете определить псевдоним типа, параметризованный над типом, заключенным в 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)

или измените свое определение, чтобы удалить допущения.

...