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

时间:2017-12-06 11:37:36

标签: 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

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

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

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

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

2 个答案:

答案 0 :(得分:7)

每个data构造函数都必须具有明确的名称,例如您使用EmptyTileXOPlayer1Player2提供的名称。使用Board,没有这样的名字; Haskell将此视为

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:monad最重要的是functor,即在该参数中某种类型和协变参数化的东西。你可以通过用多态的东西替换那些硬编码的Tile字段来使它成为monad:

data Board t = Board t t t t t t t t t
    deriving (Functor)

ApplicativeMonad实例看起来比您提议的更为复杂。

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

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

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

答案 1 :(得分:4)

您写的是data,但是typenewtype

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

或者

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

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

newtype Board = Board (Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile, Tile)

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

同样值得注意的是,抽税的游戏中的董事会不会是Monad。一方面,它需要一个类型参数,另一方面,它显然永远不会满足法律。