链接类型类,类和实例 [英] Linking typeclasses, classes, and instances

查看:45
本文介绍了链接类型类,类和实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm attempting to write a combinatorial game theory engine in Haskell. There are a few key elements.

  • 任何环境都应具有3种行为:产生基础"行为的能力.状态,在给定动作下推进状态的能力以及产生数字奖励向量的能力.我已经使用类型类 Environment 来做到这一点.

特定游戏(例如下面的Nim)应为 Environments 的实例.我使用这种抽象是因为我想编写需要 Environment 类型类而不是任何特定游戏的函数(例如Monte Carlo Tree Search).

Specific games (e.g. Nim below) should be instances of Environments. I'm using this abstraction because I'll want to write functions (e.g. Monte Carlo Tree Search) that require the Environment typeclass, not any specific game.

为了证明我没事,我为Nim游戏编写了以下跟踪程序.

To test out that I have it all right, I've written the below tracer program for the game of 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

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

When I attempt to compile, I get the following error indicating an issue with my understanding of typeclasses and instances:

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 定义中插入太多的类约束.如何在不失去灵活性的情况下修复以上框架?

I don't want to insert too many class constraints into the Environment definition, other than the reward being numeric. How do I fix the above skeleton without losing this flexibility?

推荐答案

您需要同时绑定 e s :

{-# 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

这篇关于链接类型类,类和实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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