Haskell 创建数据类型和monad时出现错误和混乱

Haskell 创建数据类型和monad时出现错误和混乱,haskell,Haskell,考虑下一段代码: data Tile = EmptyTile | X | O data Player = Player1 | Player2 instance Show Tile where show EmptyTile = " " show X = "X" show O = "O" data Board = (Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile) emptyB

考虑下一段代码:

data Tile   = EmptyTile | X | O
data Player = Player1 | Player2

instance Show Tile where
    show EmptyTile = " "
    show X         = "X"
    show O         = "O"

data Board = (Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile)

emptyBoard :: Board
emptyBoard = (EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile)

instance Monad Board where
    return x = x
    f >>= x = x
我希望那块板子是单子。但问题是我得到了以下错误-

[1 of 1] Compiling Main             ( Main.hs, Main.o )

Main.hs:17:14: error:
    Illegal binding of built-in syntax: (,,,,,,,,)

需要更改哪些内容,以便稍后将Board定义为monad

您编写的
数据
是指
类型
新类型

data Tile   = EmptyTile | X | O
data Player = Player1 | Player2

instance Show Tile where
    show EmptyTile = " "
    show X         = "X"
    show O         = "O"

type Board = (Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile)

emptyBoard :: Board
emptyBoard = (EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile,EmptyTile)
-- this won’t work
instance Monad Board where
    return x = x
    f >>= x = x


同样值得注意的是,tic税收优惠游戏中的棋盘不会是
Monad
。一方面,它需要一个类型参数,另一方面,它显然永远不会满足这些定律。

每个
数据
构造函数必须有一个明确的名称,比如你用
清空符
X
O
播放器1
播放器2
给出的名称。对于
,没有这样的名称;Haskell desugars将此视为

data Board = (,,,,,,,,) Tile Tile Tile Tile Tile Tile Tile Tile Tile
所以在这里,
(,,,,,,,)
将是“构造函数名”,但这在Haskell中实际上是不合法的,因此出现了错误

只需选择一个自定义名称,就像无聊一样

data Board = Board Tile Tile Tile Tile Tile Tile Tile Tile Tile
现在,这不可能是一个单子:一个单子主要是一个,也就是说,在某个类型上被参数化,并且在该参数中是协变的。不过,您可以将那些硬编码的
平铺
字段替换为多态字段,从而使其成为monad:

data Board t = Board t t t t t t t t t
    deriving (Functor)
但是
Applicative
Monad
实例看起来比您建议的要复杂一些

您可以考虑这样一种方法:代替手工滚动<代码>板>代码>数据结构,定义一个索引类型:

然后这将是一个没有任何进一步定义的monad,即函数monad,它具有您可能想要的语义。它往往有点低效,因为结果实际上并没有存储,但总是在现场重新计算,但对于像Tic-Tac-Toe这样的东西来说,这几乎无关紧要。(稍后,您可以通过引入

data Board t = Board t t t t t t t t t
    deriving (Functor)
data BoardIndex = Edge0 | Middle | Edge1
type Board t = (BoardIndex, BoardIndex) -> t