创建数据类型和monad时出错和混淆

Ale*_*oft 0 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)

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

instance Monad Board where
    return x = x
    f >>= x = x
Run Code Online (Sandbox Code Playgroud)

我希望那个董事会成为一个单子.但问题是我得到以下错误 -

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

Main.hs:17:14: error:
    Illegal binding of built-in syntax: (,,,,,,,,)
Run Code Online (Sandbox Code Playgroud)

需要进行哪些更改才能将Board作为monad进行定义

lef*_*out 7

每一个data构造函数必须有一个明确的名称,比如你用了EmptyTile,X,O,Player1Player2.有Board,没有这样的名字; 哈斯克尔认为这是荒谬的

data Board = (,,,,,,,,) Tile Tile Tile Tile Tile Tile Tile Tile Tile
Run Code Online (Sandbox Code Playgroud)

所以在这里,(,,,,,,,,)将是"构造函数名称",但这在Haskell中实际上并不合法,因此错误.

只需选择一个自定义名称,如无聊

data Board = Board Tile Tile Tile Tile Tile Tile Tile Tile Tile
Run Code Online (Sandbox Code Playgroud)

现在,这不可能是一个monad:monad最重要的是一个仿函数,即在该参数中对某种类型和协变进行参数化的东西.你可以把它变成一个monad,通过用Tile多态的东西替换那些硬编码的字段:

data Board t = Board t t t t t t t t t
    deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

但是ApplicativeMonad实例看起来比你提出的要多一些.

您可能会考虑这样的方法:Board您可以定义索引类型,而不是手动滚动数据结构:

data BoardIndex = Edge0 | Middle | Edge1
type Board t = (BoardIndex, BoardIndex) -> t
Run Code Online (Sandbox Code Playgroud)

那么这将是一个没有任何进一步定义的monad,即函数monad,它具有你可能想要的语义.它往往效率有点低,因为结果实际上并没有存储但总是在现场重新计算,但对于像Tic Tac Toe这样的东西几乎不重要.(通过引入备忘录,您可以在以后轻松提高效率.)