Haskell - 如何避免一遍又一遍地输入相同的上下文? [英] Haskell - How to avoid typing the same context over and over again?

查看:114
本文介绍了Haskell - 如何避免一遍又一遍地输入相同的上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始了一些爱好项目,在那里我尝试着实现这个诀窍卡 - 游戏Skat(3名玩家)。为了能够让不同类型的玩家(如人工智能,网络和本地)一起玩,我设计了一个接口使用类型类 Player :

  class Monad m =>玩家p m | p  - > m其中
playerMessage ::消息答案 - > p - > m(错误答案,p)

我使用 StateT 来包装这三名玩家:

  type PST abcmx = StateT(Players abc)mx 

但现在,我必须在每个类型签名中编写一大堆上下文:

  dealCards ::(Player am,Player bm,Player cm,RandomGen g)
=> g - > PST abcm(SomeOtherState,g)

如何避免一次又一次地写出这个大背景? p>

解决方案


  • 玩家类中唯一可以观察到的类型是



      playerMessage'::消息answer  - > m(错误答案,p)

    因此,您可以完全消除类并使用普通数据类型

     数据Player m = Player {playerMessage'
    :: Message answer - > m(错误答案,玩家m)}

    这基本上是 my previous answer

  • 另一种选择解决方案是使用GADT将上下文转换为数据类型。

      data PST abcmx其中
    PST ::( Player am,Player bm,Player cm)
    => StateT(Players a b c)m x - > PST abcmx

    换句话说,约束成为数据类型的一部分。


  • 在我看来,最好的解决方案就是废弃整个事物,并按照 TicTacToe示例,来自我的运营包。这个设计允许你在专门的monad中写入每个玩家(人类,AI,重放......),然后将所有东西注入到一个普通的解释器中。



I recently started a little hobby project, where I try to implement the trick-taking card-game Skat (for 3 players). To make it possible to have different kinds of players (like AI, network and local) playing together, I designed an interface using a typeclass Player:

class Monad m => Player p m | p -> m where
  playerMessage :: Message answer -> p -> m (Either Error answer,p)

I use a StateT to wrap up those three players:

type PST a b c m x = StateT (Players a b c) m x

But now, I have to write a big pile of context in each type signature:

dealCards :: (Player a m, Player b m, Player c m, RandomGen g)
  => g -> PST a b c m (SomeOtherState,g)

How can I avoid writing this big context again and again?

解决方案

  • The only thing you can observe from the player class is a function of type

    playerMessage' :: Message answer -> m (Either Error answer, p)
    

    Hence, you can eliminate the class entirely and use an ordinary data type

    data Player m = Player { playerMessage'
                  :: Message answer -> m (Either Error answer, Player m) }
    

    This is basically my previous answer.

  • An alternative solution is to move the context into the data type by using GADTs.

    data PST a b c m x where
        PST :: (Player a m, Player b m, Player c m)
            => StateT (Players a b c) m x -> PST a b c m x
    

    In other words, the constraints become part of the data type.

  • The best solution is, in my opinion, to scrap the whole thing and redesign it along the lines of the TicTacToe example from my operational package. This design allows you to write each player (human, AI, replay,...) in a specialized monad and later inject everything into a common interpreter.

这篇关于Haskell - 如何避免一遍又一遍地输入相同的上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆