Обновление: Когда я попытался реализовать dealCards
, я понял, что мое решение снижает безопасность типов, делая игроков взаимозаменяемыми.Таким образом, вы можете легко использовать одного игрока вместо другого, что может быть нежелательно.
Если вы не возражаете против использования ExistentialQuantification
, я думаю, что он может (и должен?) Использоваться здесь.В конце концов, функция dealCards
не должна заботиться или знать о a
, b
и c
, верно?
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
import Control.Monad.State
import System.Random
type Message answer = answer
type Error = String
class Monad m => Player p m | p -> m where
playerMessage :: Message answer -> p -> m (Either Error answer,p)
data SomePlayer m = forall p. Player p m => SomePlayer p
data Players m = Players (SomePlayer m) (SomePlayer m) (SomePlayer m)
type PST m x = StateT (Players m) m x
dealCards :: (RandomGen g, Monad m) => g -> PST m x
dealCards = undefined
Я думаю, что должно быть возможно устранить ограничение Monad
аналогичным образом.
На самом деле, в подобных случаях я чувствую, что классы типов используются слишком часто.Может быть, это новичок из Хаскелла, говорящий во мне, но я бы написал это вместо этого:
data Player m = Player { playerMessage :: Message answer -> m (Either Error answer, Player m) }