首页 > 解决方案 > 链接类型类、类和实例

问题描述

我正在尝试在 Haskell 中编写一个组合博弈论引擎。有几个关键要素。

为了测试我是否一切正常,我为 Nim 游戏编写了以下跟踪程序。

class Environment e where
    baseState :: e -> s
    nextState :: e -> s -> a -> s
    reward :: (Num r) => e -> s -> a -> [r]


data Game = Game { players :: Int
                 , initial_piles :: [Int]
                 } deriving (Show)

data State = State { player :: Int
                   , piles :: [Int]} deriving (Show)

instance Environment Game where
    baseState game = State{player=0, piles=initial_piles game}
    nextState game state action = State{player=0, piles=piles state}
    reward game state action = [0, 0]

newGame :: Int -> [Int] -> Game
newGame players piles = Game{players=players, initial_piles=piles}


main = do
    print "Hello, world!"
    let game = newGame 2 [3,4,5]
    print game

当我尝试编译时,我收到以下错误,表明我对类型类和实例的理解存在问题:

randm@soundgarden:~/Projects/games/src/Main$ ghc -o basic basic.hs
[1 of 1] Compiling Main             ( basic.hs, basic.o )

basic.hs:15:22: error:
    • Couldn't match expected type ‘s’ with actual type ‘State’
      ‘s’ is a rigid type variable bound by
        the type signature for:
          baseState :: forall s. Game -> s
        at basic.hs:15:5-13
    • In the expression: State {player = 0, piles = initial_piles game}
      In an equation for ‘baseState’:
          baseState game = State {player = 0, piles = initial_piles game}
      In the instance declaration for ‘Environment Game’
    • Relevant bindings include
        baseState :: Game -> s (bound at basic.hs:15:5)
   |
15 |     baseState game = State{player=0, piles=initial_piles game}
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

basic.hs:16:35: error:
    • Couldn't match expected type ‘s’ with actual type ‘State’
      ‘s’ is a rigid type variable bound by
        the type signature for:
          nextState :: forall s a. Game -> s -> a -> s
        at basic.hs:16:5-13
    • In the expression: State {player = 0, piles = piles state}
      In an equation for ‘nextState’:
          nextState game state action
            = State {player = 0, piles = piles state}
      In the instance declaration for ‘Environment Game’
    • Relevant bindings include
        state :: s (bound at basic.hs:16:20)
        nextState :: Game -> s -> a -> s (bound at basic.hs:16:5)
   |
16 |     nextState game state action = State{player=0, piles=piles state}
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我不想在Environment定义中插入太多的类约束,除了奖励是数字的。如何在不失去这种灵活性的情况下修复上述骨架?

标签: haskell

解决方案


您需要同时绑定es

{-# LANGUAGE MultiParamTypeClasses #-}

class Environment e s where
    baseState :: e -> s
    nextState :: e -> s -> a -> s
    reward :: (Num r) => e -> s -> a -> [r]


data Game = Game { players :: Int
                 , initial_piles :: [Int]
                 } deriving (Show)

data State = State { player :: Int
                   , piles :: [Int]} deriving (Show)

instance Environment Game State where
    baseState game = State{player=0, piles=initial_piles game}
    nextState game state action = State{player=0, piles=piles state}
    reward game state action = [0, 0]

newGame :: Int -> [Int] -> Game
newGame players piles = Game{players=players, initial_piles=piles}


main = do
    print "Hello, world!"
    let game = newGame 2 [3,4,5]
    print game

推荐阅读