(A simple way) to make calling a function with a certain value is a compile-time error? - haskell

I think it's not possible (or requires certain language extensions) to make a function like
f :: Maybe Int
f (Just n) = n
f Nothing = ... -- a compile-time error
There's also no way you can make a function like:
g :: MyClass a => Int -> a
g n | n < 10 = TypeClassInstance
| otherwise = OtherTypeClassInstance
So, I'm working on this tic-tac-toe API from the famous NICTA FP course that is required to do things like:
takeBack: takes either a finished board or a board in-play that has had at least one move and returns a board in-play. It is a compile-time type error to call this function on an empty board.
I think it's possible to do some really fancy type-level programming. But even if it is then I don't think someone who has just taken a 2-day introduction to functional programming could know it. Or did I miss something?
Update
Based the example given by #user2407038 and clarification from #Cirdec, I write this and it does make a compile-time error when you try to takeBack on an empty board which is great.
However -- moving the goal posts a little -- this trick seems limited. There's another requirement that you can't move on a game that's already over.
move: takes a tic-tac-toe board and position and moves to that position (if not occupied) returning a new board. This function can only be called on a board that is empty or in-play. Calling move on a game board that is finished is a compile-time type error.
It doesn't seem like a simple trick of having the type count the moves can be used in the case of complicated logic to determine whether the game is over.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
data N = S N | Z
data Stat
= Empty
| InPlay
| Won
deriving Show
data Board (n :: N)
= Board Stat [Int]
deriving Show
newBoard :: Board Z
newBoard = Board Empty []
move :: Int -> Board a -> Board (S a)
move x (Board Empty []) = Board InPlay [x]
move x (Board InPlay xs) = Board Won (x:xs)
takeBack :: Board (S a) -> Board a
takeBack (Board InPlay [x]) = Board Empty []
takeBack (Board InPlay (x:xs)) = Board InPlay xs
takeBack (Board Won (x:xs)) = Board InPlay xs
main :: IO ()
main = do
let
brd = newBoard -- Empty
m1 = move 1 brd -- InPlay
m2 = move 2 m1 -- Won
m3 = move 3 m2 -- Can't make this a compile-time error with this trick
tb2 = takeBack m2 -- Won
tb1 = takeBack tb2 -- InPlay
tb0 = takeBack tb1 -- Empty -> Compile-time error Yay!
return ()

You can do something like your first example with a GADT (generalized algebraic datatype);
data SMaybe (a :: Maybe *) where
SJust :: a -> SMaybe (Just a)
SNothing :: SMaybe Nothing
f :: SMaybe (Just a) -> a
f (SJust a) = a
-- f SNothing = undefined -- Including this case is a compile time error
Although I doubt this has much use. The simplest solution to the board thing is probably have a phantom type parameter on your Board datatype:
type Empty = False
type NonEmpty = True
data Board (b :: Bool) = Board ...
newBoard :: Board Empty
newBoard = Board ...
setAt :: (Int, Int) -> Bool -> Board a -> Board NonEmpty
setAt p b (Board ...) = ...
takeBack :: Board NonEmpty -> Board NonEmpty
takeBack (Board ...) = ...
You can increase the amount of information stored on the type level if you like. For example, you can have the number of filled "cells":
data N = S N | Z -- The naturals
data Board (n :: N) = Board ...
newBoard :: Board Z
newBoard = Board ...
setAt :: (Int, Int) -> Bool -> Board a -> Board (S a)
setAt = ...
takeBack :: Board (S n) -> Board (S n)
takeBack = ...
The examples above use DataKinds for convenience, but it isn't needed.

One easy way to accomplish something like this without invoking any type-level programming is a smart constructor. To make a smart constructor, you don't export the real constructor for a data type and instead provide a function that only creates values of the type that meet your other rules.
We can tackle the example problem by making smart constructors that represent a proof that a board is Playable, Finished, or NonEmpty.
type Position = (Int, Int)
type Player = Bool
data Board = Board -- ...
deriving (Eq, Show, Read, Ord)
newtype Playable = Playable {getPlayable :: Board}
deriving (Eq, Ord, Show)
newtype Finished = Finished {getFinished :: Board}
deriving (Eq, Ord, Show)
newtype NonEmpty = NonEmpty {getNonEmpty :: Board}
deriving (Eq, Ord, Show)
We are careful not to provide instances that could create any of these types; for example, we didn't derive Read instances for them. The only exported functions that will create these will first check the necessary conditions.
playable :: Board -> Maybe Playable
playable = undefined
finished :: Board -> Maybe Finished
finished = undefined
nonEmpty :: Board -> Maybe NonEmpty
nonEmpty = undefined
When we export the types from the module, we won't export their constructors
module TicTacToe (
Playable (getPlayable),
Finished (getFinished),
NonEmpty (getNonEmpty),
playable,
finished,
nonEmpty,
Position,
Player,
Board (..),
move,
whoWon,
takeBack,
playerAt
) where
The remaining functions can require that the client code has already gotten a type-level proof of the necessary property before invoking the function.
move :: Position -> Playable -> Board
move = undefined
whoWon :: Finished -> Player
whoWon = undefined
takeBack :: NonEmpty -> Board
takeBack = undefined
For this example problem, the smart constructors accomplished absolutely nothing. Any library user is going to define helper functions so that they only have to concern themselves with Maybe and not with any of these other special Board types.
move' :: Position -> Board -> Maybe Board
move' p = fmap (move p) . playable
whoWon' :: Board -> Maybe Player
whoWon' = fmap whoWon . finished
takeBack' :: Board -> Maybe Board
takeBack' = fmap takeBack . nonEmpty
This suggests that using Maybe in the interface is sufficient, and the requirements for compile-time errors in the exercise are superfluous. This also falls in line with the following requested function, which doesn't require a type-level proof that someone has moved in that position before being used.
playerAt :: Position -> Board -> Maybe Player
playerAt = undefined
Using type-level proofs of properties is more advantageous when there are many transformations for which those properties are invariant or can be easily deduced.

Related

A way to generalize Haskell's Either type for arbitrarily many types?

I am creating a turn based game. I want to define a datatype that encodes one type out of many possible types. Here is the motivating example:
I have defined a Turn type using GADTs, so the type of each value of Turn a says something about it's value.
data Travel
data Attack
data Flee
data Quit
data Turn a where
Travel :: Location -> Turn Travel
Attack :: Int -> Turn Attack
Flee :: Turn Flee
Quit :: Turn Quit
Now I can write types like this decideTravel :: GameState -> Turn Travel, very expressive and nice.
The problem arises when I want to return one of multiple possible turn types. I want to write functions similar to the following:
-- OneOf taking two types
decideFightingTurn :: GameState -> OneOf (Turn Attack) (Turn Flee)
-- OneOf takes three types
decideTurn :: GameState -> OneOf (Turn Attack) (Turn Travel) (Turn Quit)
Where this OneOf datatype carries the notion of "one type out of many possible types". The problem lies in defining this datatype, I need to somehow handle a list of types at the type level.
There are two subpar solutions I have as of now:
Solution 1: Create a wrapper sum type
Simply create a new type that has a constructor for each Turn a constructor:
data AnyTurn
= TravelTurn (Turn Travel)
| TravelAttack (Turn Attack)
| TravelFlee (Turn Flee)
| TravelQuit (Turn Quit)
This doesn't help me in the way I want it to. Now I have to pattern match all cases of AnyTurn and account for invalid input types. Additionally the type level information is obscured by the AnyTurn type, since it fails to indicate which specific turns are actually possible at the type level.
Solution 2: Create "Either" types for different numbers of types
This solution gives me what I want at the type level, but is cumbersome to use. Basically create an Either-like type for any number of combinations, like so:
data OneOf2 a b
= OneOf2A a
| OneOf2B b
data OneOf3 a b c
= OneOf3A a
| OneOf3B b
| OneOf3C c
-- etc, for as many as are needed.
This conveys what I want at the type level, so I can now write the previous examples as:
decideFightingTurn :: GameState -> OneOf2 (Turn Travel) (Turn Flee)
decideTurn :: GameState -> OneOf3 (Turn Attack) (Turn Travel) (Turn Quit)
This works, however it would be nice to express this with just one type OneOf. Is there any way to write the generalized OneOf type in Haskell?
Something like this, I guess:
data OneOf as where
ThisOne :: a -> OneOf (a : as)
Later :: OneOf as -> OneOf (a : as)
Then you can write, for example:
decideFightingTurn :: GameState -> OneOf [Turn Travel, Turn Flee]
You might also like to:
type family Map f xs where
Map f '[] = '[]
Map f (x:xs) = f x : Map f xs
This way you can write something like:
decideFightingTurn :: GameState -> OneOf (Map Turn [Travel, Flee])
Or you could build the Map into the GADT if you think you'll always be doing it:
data OneOfF f as where
ThisOneF :: f a -> OneOfF f (a : as)
LaterF :: OneOfF f as -> OneOfF f (a : as)
And then:
decideFightingTurn :: GameState -> OneOfF Turn [Travel, Flee]
Various things can be done to make this more efficient if that becomes a concern; the first thing I'd try would be using binary indexing rather than unary as shown here.
There's a Haskell library called row-types that might give you what you want. Specifically, it provides an extensible variant that is kind of like Either but tagged and with arbitrarily many options.
In your case, you could make your types:
import Data.Row
decideFightingTurn :: GameState -> Var ("travel" .== Turn Travel .+ "flee" .== Turn Flee)
decideTurn :: GameState -> Var ("attack" .== Turn Attack .+ "travel" .== Turn Travel .+ "quit" .== Turn Quit)
The easiest way to work with variants is to turn OverloadedLabels on. Then, to create one, you write:
decideFightingTurn gs = case gs of
Foo -> IsJust #travel $ Travel loc
Bar -> IsJust #flee Flee
Deconstructing can be done in a few different ways. If you just want to check for a particular type, you can use trial or view (exported by Data.Row.Variants), but if you want to deal with all the options at once, you may want to use switch. You'd write something like this:
handleTravelOrFlee :: Var ("travel" .== Turn Travel .+ "flee" .== Turn Flee) -> GameState -> GameState
handleTravelOrFlee v gs = switch v $
#travel .== (\(Travel loc) -> updateGameStateWithLoc gs loc)
.+ #flee .== (\Flee -> updateGameStateFlee gs)
Check out the documentation and the examples file for more info.
Another option could be activating and deactivating constructors in the sum type:
{-# LANGUAGE GADTs, TypeOperators, DataKinds, PolyKinds,
TypeFamilies, StandaloneKindSignatures #-}
{-# OPTIONS_GHC -Werror=incomplete-patterns -Werror=overlapping-patterns #-}
import Data.Void
import Data.Kind
data TurnType =
Travel
| Attack
| Flee
| Quit
type Turn :: TurnType -> Type
data Turn tt where
TurnTravel :: Location -> Turn Travel
TurnAttack :: Int -> Turn Attack
TurnFlee :: Turn Flee
TurnQuit :: Turn Quit
type X :: TurnType -> [TurnType] -> Type
type family X x tts :: Type where
X _ '[] = Void
X x (x : xs) = ()
X x (_ : xs) = X x xs
-- Exhaustiveness checker knows that branches where
-- X returns Void are impossible.
type AnyTurn :: [TurnType] -> Type
data AnyTurn allowed
= TravelTurn !(X Travel allowed) (Turn Travel)
| TravelAttack !(X Attack allowed) (Turn Attack)
| TravelFlee !(X Flee allowed) (Turn Flee)
| TravelQuit !(X Quit allowed) (Turn Quit)
Putting it to work:
someTurn :: AnyTurn '[Travel, Attack]
someTurn = TravelAttack () (TurnAttack 0)
-- This doesn't give an exhaustiveness error because other branches are impossible.
-- The problem is that we now have those annoying () cluttering every match.
turn2string :: AnyTurn '[Travel, Attack] -> String
turn2string t = case t of
TravelTurn () _ -> "foo"
TravelAttack () _ -> "bar"
-- TravelQuit _ _ -> "doesn't compile"

couldn't match expected type (newtype)

I'm working on a function
createTypeBoard :: (Int, Int) -> CellType -> Board
using these types
newtype Board = Board [(Cell, CellType)] deriving(Eq)
data CellType = Mine
| Flag
| Void
| Enumerated Int
| Undiscovered
deriving Eq
type Cell = (Int, Int)
createTypeBoard (2,2) Mine should be: Board [((1,1), X), ((1,2), X), ((2,1), X), ((2,2), X)]
(X is the show instance of Mine)
my idea was to use zip:
createTypeBoars (a, b) c = zip (createCells (a, b)) [c]
but I keep getting an error
• Couldn't match expected type ‘Board’
with actual type ‘[(Cell, CellType)]’
• In the expression: zip (createCells (a, b)) [Flag]
In an equation for ‘createTypeBoard’:
createTypeBoard (a, b) Flag = zip (createCells (a, b)) [Flag]
Board basically is [(Cell, CellType)] so I don't really get what the problem is :(
You declared Board with newtype, but you're trying to use it as if you declared it with type. Two choices to fix it:
Declare board like this instead: type Board = [(Cell, CellType)]
Use the Board data constructor in createTypeBoard, like this: createTypeBoard (a, b) c = Board $ zip (createCells (a, b)) [c]
For more information on the difference between type and newtype, which may affect your decision on which fix to go with, see Haskell type vs. newtype with respect to type safety and/or The difference between type and newtype in Haskell.

On Haskell, what is the linguistic way to represent a card effect for a card game?

I have a simple one-player Card Game:
data Player = Player {
_hand :: [Card],
_deck :: [Card],
_board :: [Card]}
$(makeLenses ''Player)
Some cards have an effect. For example, "Erk" is a card with the following effect:
Flip a coin. If heads, shuffle your deck.
I've implemented it as such:
shuffleDeck :: (MonadRandom m, Functor m) => Player -> m Player
shuffleDeck = deck shuffleM
randomCoin :: (MonadRandom m) => m Coin
randomCoin = getRandom
flipCoin :: (MonadRandom m) => m a -> m a -> m a
flipCoin head tail = randomCoin >>= branch where
branch Head = head
branch Tail = tail
-- Flip a coin. If heads, shuffle your deck.
erk :: (MonadRandom m, Functor m) => Player -> m Player
erk player = flipCoin (deck shuffleM player) (return player)
While this certainly does the job, I find an issue on the forced coupling to the Random library. What if I later on have a card that depends on another monad? Then I'd have to rewrite the definition of every card defined so far (so they have the same type). I'd prefer a way to describe the logic of my game entirely independent from the Random (and any other). Something like that:
erk :: CardAction
erk = do
coin <- flipCoin
case coin of
Head -> shuffleDeck
Tail -> doNothing
I could, later on, have a runGame function that does the connection.
runGame :: (RandomGen g) => g -> CardAction -> Player -> Player
I'm not sure that would help. What is the correct, linguistic way to deal with this pattern?
This is one of the engineering problems the mtl library was designed to solve. It looks like you're already using it, but don't realize its full potential.
The idea is to make monad transformer stacks easier to work with using typeclasses. A problem with normal monad transformer stacks is that you have to know all of the transformers you're using when you write a function, and changing the stack of transformers changes how lifts work. mtl solves this by defining a typeclass for each transformer it has. This lets you write functions that have a class constraint for each transformer it requires but can work on any stack of transformers that includes at least those.
This means that you can freely write functions with different sets of constraints and then use them with your game monad, as long as you game monad has at least those capabilities.
For example, you could have
erk :: MonadRandom m => ...
incr :: MonadState GameState m => ...
err :: MonadError GameError m => ...
lots :: (MonadRandom m, MonadState GameState m) => ...
and define your Game a type to support all of those:
type Game a = forall g. RandT g (StateT GameState (ErrorT GameError IO)) a
You'd be able to use all of these interchangeably within Game, because Game belongs to all of those typeclasses. Moreover, you wouldn't have to change anything except the definition of Game if you wanted to add more capabilities.
There's one important limitation to keep in mind: you can only access one instance of each transformer. This means that you can only have one StateT and one ErrorT in your whole stack. This is why StateT uses a custom GameState type: you can just put all of the different things you may want to store throughout your game into that one type so that you only need one StateT. (GameError does the same for ErrorT.)
For code like this, you can get away with just using the Game type directly when you define your functions:
flipCoin :: Game a -> Game a -> Game a
flipCoin a b = ...
Since getRandom has a type polymorphic over m itself, it will work with whatever Game happens to be as long as it has at least a RandT (or something equivalent) inside.
So, to answer you question, you can just rely on the existing mtl typeclasses to take care of this. All of the primitive operations like getRandom are polymorphic over their monad, so they will work with whatever stack you end up with in the end. Just wrap all your transformers into a type of your own (Game), and you're all set.
This sounds like a good use-case for the operational package. It lets you define a monad as a set of operations and their return types using a GADT and you can then easily build an interpreter function like the runGame function you suggested. For example:
{-# LANGUAGE GADTs #-}
import Control.Monad.Operational
import System.Random
data Player = Player {
_hand :: [Card],
_deck :: [Card],
_board :: [Card]}
data Coin = Head | Tail
data CardOp a where
FlipCoin :: CardOp Coin
ShuffleDeck :: CardOp ()
type CardAction = Program CardOp
flipCoin :: CardAction Coin
flipCoin = singleton FlipCoin
shuffleDeck :: CardAction ()
shuffleDeck = singleton ShuffleDeck
erk :: CardAction ()
erk = do
coin <- flipCoin
case coin of
Head -> shuffleDeck
Tail -> return ()
runGame :: RandomGen g => g -> CardAction a -> Player -> Player
runGame = step where
step g action player = case view action of
Return _ -> player
FlipCoin :>>= continue ->
let (heads, g') = random g
coin = if heads then Head else Tail
in step g' (continue coin) player
...etc...
However, you might also want to consider just describing all your card actions as a simple ADT without do-syntax. I.e.
data CardAction
= CoinFlip CardAction CardAction
| ShuffleDeck
| DoNothing
erk :: CardAction
erk = CoinFlip ShuffleDeck DoNothing
You can easily write an interpreter for the ADT and as a bonus you can also e.g. generate the card's rule text automatically.

choosing a monad at runtime

I'm trying to write a two-player game in Haskell, such as checkers. I envision having types GameState, Move, and a function result :: GameState -> Move -> GameState that defines the game rules. I want to have both human and automated players, and I figured I'd do this by having a typeclass:
class Player p m | p -> m where
selectMove :: p -> GameState -> m Move
where the idea would be that m could be Identity for a basic AI player, IO for a human, State for an AI that maintains state across moves, etc. The question is how to go from these to the overall game loop. I figure I could define something like:
Player p1 m1, Player p2 m2 => moveList :: p1 -> p2 -> GameState -> m1 m2 [Move]
a monadic function that takes in the players and initial state, and returns the lazy list of moves. But then on top of this let's say I want a text-based interface that, say, allows first selecting each player from a list of possibilities, then causes the game to be played. So I'd need:
playGame :: IO ()
I can't see how to define playGame given moveList in a generic way. Or is my overall approach not right?
EDIT: thinking further about it, I don't even see how to define moveList above. E.g., if player 1 was a human, so IO, and player 2 was a stateful AI, so State, the first move of player 1 would have type IO Move. Then player 2 would have to take the resulting state of type IO GameState and produce a move of type State IO Move, and player 1's next move would be of type IO State IO Move? That doesn't look right.
There are two parts to this question:
How to mix a monad-independent chess-playing framework with incremental monad-specific input
How to specify the monad-specific part at run time
You solve the former problem using a generator, which is a special case of a free monad transformer:
import Control.Monad.Trans.Free -- from the "free" package
type GeneratorT a m r = FreeT ((,) a) m r
-- or: type Generator a = FreeT ((,) a)
yield :: (Monad m) => a -> GeneratorT a m ()
yield a = liftF (a, ())
GeneratorT a is a monad transformer (because FreeT f is a monad transformer, for free, when f is a Functor). This means we can mix yield (which is polymorphic in the base monad), with monad-specific calls by using lift to invoke the base monad.
I'll define some fake chess moves just for this example:
data ChessMove = EnPassant | Check | CheckMate deriving (Read, Show)
Now, I'll define an IO based generator of chess moves:
import Control.Monad
import Control.Monad.Trans.Class
ioPlayer :: GeneratorT ChessMove IO r
ioPlayer = forever $ do
lift $ putStrLn "Enter a move:"
move <- lift readLn
yield move
That was easy! We can unwrap the result one move at a time using runFreeT, which will only demand the player input a move when you bind the the result:
runIOPlayer :: GeneratorT ChessMove IO r -> IO r
runIOPlayer p = do
x <- runFreeT p -- This is when it requests input from the player
case x of
Pure r -> return r
Free (move, p') -> do
putStrLn "Player entered:"
print move
runIOPlayer p'
Let's test it:
>>> runIOPlayer ioPlayer
Enter a move:
EnPassant
Player entered:
EnPassant
Enter a move:
Check
Player entered:
Check
...
We can do the same thing using the Identity monad as the base monad:
import Data.Functor.Identity
type Free f r = FreeT f Identity r
runFree :: (Functor f) => Free f r -> FreeF f r (Free f r)
runFree = runIdentity . runFreeT
NoteThe transformers-free packages defines these already (Disclaimer: I wrote it and Edward merged its functionality was merged into the free package. I only keep it for teaching purposes and you should use free if possible).
With those in hand, we can define pure chess move generators:
type Generator a r = Free ((,) a) r
-- or type Generator a = Free ((,) a)
purePlayer :: Generator ChessMove ()
purePlayer = do
yield Check
yield CheckMate
purePlayerToList :: Generator ChessMove r -> [ChessMove]
purePlayerToList p = case (runFree p) of
Pure _ -> []
Free (move, p') -> move:purePlayerToList p'
purePlayerToIO :: Generator ChessMove r -> IO r
purePlayerToIO p = case (runFree p) of
Pure r -> return r
Free (move, p') -> do
putStrLn "Player entered: "
print move
purePlayerToIO p'
Let's test it:
>>> purePlayerToList purePlayer
[Check, CheckMate]
Now, to answer your next question, which is how to choose the base monad at run time. This is easy:
main = do
putStrLn "Pick a monad!"
whichMonad <- getLine
case whichMonad of
"IO" -> runIOPlayer ioPlayer
"Pure" -> purePlayerToIO purePlayer
"Purer!" -> print $ purePlayerToList purePlayer
Now, here is where things get tricky. You actually want two players, and you want to specify the base monad for both of them independently. To do this, you need a way to retrieve one move from each player as an action in the IO monad and save the rest of the player's move list for later:
step
:: GeneratorT ChessMove m r
-> IO (Either r (ChessMove, GeneratorT ChessMove m r))
The Either r part is in case the player runs out of moves (i.e. reaches the end of their monad), in which case the r is the block's return value.
This function is specific to each monad m, so we can type class it:
class Step m where
step :: GeneratorT ChessMove m r
-> IO (Either r (ChessMove, GeneratorT ChessMove m r))
Let's define some instances:
instance Step IO where
step p = do
x <- runFreeT p
case x of
Pure r -> return $ Left r
Free (move, p') -> return $ Right (move, p')
instance Step Identity where
step p = case (runFree p) of
Pure r -> return $ Left r
Free (move, p') -> return $ Right (move, p')
Now, we can write our game loop to look like:
gameLoop
:: (Step m1, Step m2)
=> GeneratorT ChessMove m1 a
-> GeneratorT ChessMove m2 b
-> IO ()
gameLoop p1 p2 = do
e1 <- step p1
e2 <- step p2
case (e1, e2) of
(Left r1, _) -> <handle running out of moves>
(_, Left r2) -> <handle running out of moves>
(Right (move1, p2'), Right (move2, p2')) -> do
<do something with move1 and move2>
gameLoop p1' p2'
And our main function just selects which players to use:
main = do
p1 <- getStrLn
p2 <- getStrLn
case (p1, p2) of
("IO", "Pure") -> gameLoop ioPlayer purePlayer
("IO", "IO" ) -> gameLoop ioPlayer ioPlayer
...
I hope that helps. That was probably a bit over kill (and you can probably use something simpler than generators), but I wanted to give a general tour of cool Haskell idioms that you can sample from when designing your game. I type-checked all but the last few code blocks, since I couldn't come up with a sensible game logic to test on the fly.
You can learn more about free monads and free monad transformers if those examples didn't suffice.
My advice has two main parts:
Skip defining a new type class.
Program to the interfaces defined by existing type classes.
For the first part, what I mean is you should consider creating a data type like
data Player m = Player { selectMove :: m Move }
-- or even
type Player m = m Move
What the second part means is to use classes like MonadIO and MonadState to keep your Player values polymorphic, and choose an appropriate monad instance only at the end after combining all the players. For example, you might have
computerPlayer :: MonadReader GameState m => Player m
randomPlayer :: MonadRandom m => Player m
humanPlayer :: (MonadIO m, MonadReader GameState m) => Player m
Perhaps you will find there are other players you want, too. Anyway, the point of this is that once you've created all these players, if they are typeclass polymorphic as above, you may choose a particular monad that implements all the required classes and you are done. For example, for these three, you might choose ReaderT GameState IO.
Good luck!

Haskell data structures oddity

I've been attempting to write a small file to try out a bag-like data structure. So far my code is as follows:
data Fruit = Apple | Banana | Pear deriving (Eq, Show)
data Bag a = EmptyBag | Contents [(a, Integer)]
emptyBag :: Bag a
emptyBag = EmptyBag
unwrap :: [a] -> a
unwrap [x] = x
isObject theObject (obj, inte) = theObject == obj
count :: Bag a -> a -> Integer
count (Contents [xs]) theObject = snd (unwrap (filter (isObject theObject) [xs]))
count EmptyBag _ = 0
But when I try and run it I get the error
Could not deduce (Eq a) from the context ()
arising from a use of 'isObject' at ....
Whereas when I take the count function out and call
snd(unwrap(filter (isObject Banana) [(Apple,1),(Banana,2)]))
it happily returns 2.
Any clues on why this is, or advice on writing this kind of data structure would be much appreciated.
(==) can only be used in a context that includes Eq, but when you declared count you didn't include that context. If I'm reading correctly, that would be
count :: Eq a => Bag a -> a -> Integer
If you declare count without including the type, you can ask ghci for the inferred type; or just ask for the inferred type of snd (unwrap (filter (isObject Banana) [(Apple,1),(Banana,2)]))

Resources