Pergunta

Estou trabalhando em meu primeiro projeto Haskell 'real' e, ao mesmo tempo, tentando entender fornecimento de eventos.(Pareceu uma boa combinação;a fonte de eventos é uma forma bastante funcional de analisar os dados.)

Eu bati em uma parede tentando descobrir como desserializar meus eventos em dados Haskell fortemente digitados.Existem duas forças opostas em ação aqui:

  1. Não deveria ser possível aplicar um evento ao tipo errado de agregação.Este requisito sugere que preciso de um tipo de evento separado para cada agregado no meu sistema:

    data PlayerEvent = PlayerCreated Name | NameUpdated Name

    data GameEvent = GameStarted PlayerID PlayerID | MoveMade PlayerID Move

    Para usar esses eventos você usaria funções com tipos como applyEvent :: Game -> GameEvent -> Game.

  2. Preciso ser capaz de serializar e desserializar entre eventos fortemente digitados e objetos JSON.Este requisito sugere que preciso de polimórfico serialise e deserialise funções:

    class Event e where serialise :: e -> ByteString

    deserialise :: Event e => ByteString -> e

Esse último deserialise função é o problema.A assinatura de tipo diz que os chamadores podem solicitar qualquer instancia de Event, mas é claro que o tipo que você recebe depende do ByteString que entrou e é determinado em tempo de execução.

Aqui está uma implementação de stub que não será compilada:

deserialise :: Event e => ByteString -> e
deserialise _ = GameStarted 0 0

E a mensagem de erro:

Could not deduce (e ~ GameEvent)
from the context (Event e)
  bound by the type signature for
             deserialise :: Event e => ByteString -> e
  at ...:20:16-41
  `e' is a rigid type variable bound by
      the type signature for deserialise :: Event e => ByteString -> e
      at ...:20:16
In the return type of a call of `GameStarted'
In the expression: GameStarted 0 0
In an equation for `deserialise':
    deserialise _ = GameStarted 0 0

Esse tipo de coisa é simples em uma linguagem orientada a objetos com reflexão.Acho difícil acreditar que encontrei um problema para o qual o sistema de tipos Java é mais expressivo que o de Haskell.

Sinto que devo estar perdendo uma abstração importante aqui.Qual é a maneira correta de implementar os requisitos acima?

Foi útil?

Solução

Se você fizer deserialize um membro do Event class, então você não terá problemas:

class Event e where
    serialize :: e -> ByteString
    deserialize :: ByteString -> e

instance Event PlayerEvent where
    ...

instance Event GameEvent where
    ...
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top