考虑下一段代码:
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
答案 0 :(得分:7)
每个data
构造函数都必须具有明确的名称,例如您使用EmptyTile
,X
,O
,Player1
和Player2
提供的名称。使用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)
但Applicative
和Monad
实例看起来比您提议的更为复杂。
您可以考虑这样的方法:您可以定义索引类型,而不是手动滚动Board
数据结构:
data BoardIndex = Edge0 | Middle | Edge1
type Board t = (BoardIndex, BoardIndex) -> t
然后这将是一个没有任何进一步定义的monad,即 function monad ,它具有你可能想要的语义。它往往效率有点低,因为结果实际上并没有存储但总是在现场重新计算,但对于像Tic Tac Toe这样的东西几乎不重要。 (通过引入memoisation,您可以在以后轻松提高效率。)
答案 1 :(得分:4)
您写的是data
,但是type
或newtype
:
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
。一方面,它需要一个类型参数,另一方面,它显然永远不会满足法律。