gpt4 book ai didi

haskell - Haskell 中的强类型事件

转载 作者:行者123 更新时间:2023-12-04 15:22:50 25 4
gpt4 key购买 nike

我正在做我的第一个“真正的”Haskell 项目,同时试图让我的头脑了解 event sourcing . (这似乎是一个很好的匹配;事件溯源是一种查看数据的相当实用的方式。)

我在试图弄清楚如何将我的事件反序列化为强类型的 Haskell 数据时遇到了困难。这里有两种相反的力量在起作用:

  • 不可能将事件应用于错误类型的聚合。此要求表明我需要为系统中的每个聚合使用单独类型的事件:
    data PlayerEvent = PlayerCreated Name | NameUpdated Namedata GameEvent = GameStarted PlayerID PlayerID | MoveMade PlayerID Move
    要使用这些事件,您可以使用类型为 applyEvent :: Game -> GameEvent -> Game 的函数。 .
  • 我需要能够在强类型事件和 JSON 对象之间进行序列化和反序列化。这个要求表明我需要多态 serialisedeserialise功能:
    class Event e where serialise :: e -> ByteStringdeserialise :: Event e => ByteString -> e

  • 最后 deserialise功能是问题。类型签名表明调用者可以请求 Event 的任何实例。 , 但当然你得到的类型取决于 ByteString进来并在运行时确定。

    这是一个无法编译的 stub 实现:
    deserialise :: Event e => ByteString -> e
    deserialise _ = GameStarted 0 0

    和错误信息:
    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

    这种事情在带有反射的面向对象语言中很简单。我很难相信我发现了一个问题,Java 的类型系统比 Haskell 的类型系统更具表现力。

    我觉得我必须在这里错过一个关键的抽象。实现上述要求的正确方法是什么?

    最佳答案

    如果您制作 deserialize Event 的成员类,那么你不会有任何问题:

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

    instance Event PlayerEvent where
    ...

    instance Event GameEvent where
    ...

    关于haskell - Haskell 中的强类型事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22026038/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com