Haskell Chesshs and Array Error How To Define `board :: Array (Int, Int) (Maybe Piece)`

huangapple go评论61阅读模式
英文:

Haskell Chesshs and Array Error How To Define `board :: Array (Int, Int) (Maybe Piece)`

问题

I am trying to build a Board in the library chesshs.

-- from chesshs source code:

data Board = Board { turn :: Color
                   , castlingAvail :: String
                   , enpassant :: Maybe (Int, Int)
                   , board :: Array (Int, Int) (Maybe Piece)
                   } deriving (Eq)

so I am trying to create a Board with the following:

*MyLib Data.Array Chess> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = Array (0,0) (Just (Piece White Pawn))
}

but I get the following error, as if Array doesn't exist, Strange because is what it appears as type signature in the board parameter as per chesshs source code:

<interactive>:103:71: error:
     Data constructor not in scope:
        Array :: (a0, b0) -> Maybe Piece -> Array (Int, Int) (Maybe Piece)
     Perhaps you meant variable array (imported from Data.Array)

so I try substituting Array for array (not quite sure why Array doesn't work and if array is just the way to create an Array)

*MyLib Data.Array Chess Chess.PGN> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = array (0,0) (Just (Piece White Pawn))
}

but it doesn't work and I receive this error message:

<interactive>:104:84: error:
     Couldn't match expected type [((Int, Int), Maybe Piece)]
                  with actual type Maybe Piece
     In the second argument of array, namely
        (Just (Piece White Pawn))
      In the board field of a record
      In the expression:
        Board
          {turn = White, castlingAvail = "", enpassant = Nothing,
           board = array (0, 0) (Just (Piece White Pawn))}

Which makes sense because checking the array type

array :: Ix i => (i, i) -> [(i, e)] -> Array i e

so I try the following:

*MyLib Data.Array Chess> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = array (0,0) [((0,0), (Just (Piece White Pawn))]
}

which gives me this error:

<interactive>:108:78: error:
     No instance for (Num (Int, Int)) arising from the literal 0
     In the expression: 0
      In the first argument of array, namely (0, 0)
      In the board field of a record

Which leaves me very confused.. not quite sure why ghci interaction drives me to use a type different from what it appears in the source code of chesshs Board and why it anyway drives me to an error that I don't understand.

英文:

I am trying to build a Board in the library chesshs.

-- from chesshs source code:

data Board = Board { turn :: Color
                   , castlingAvail :: String
                   , enpassant :: Maybe (Int, Int)
                   , board :: Array (Int, Int) (Maybe Piece)
                   } deriving (Eq)

so I am trying to create a Board with the following:

*MyLib Data.Array Chess> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = Array (0,0) (Just (Piece White Pawn))
}

but I get the following error, as if Array doesn't exist, Strange because is what it appears as type signature in the board parameter as per chesshs source code:

<interactive>:103:71: error:
    • Data constructor not in scope:
        Array :: (a0, b0) -> Maybe Piece -> Array (Int, Int) (Maybe Piece)
    • Perhaps you meant variable ‘array’ (imported from Data.Array)

so I try substituting Array for array (not quite sure why Array doesn't work and if array is just the way to create an Array)

*MyLib Data.Array Chess Chess.PGN> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = array (0,0) (Just (Piece White Pawn))
}

but it doesn't work and I receive this error message:

<interactive>:104:84: error:
    • Couldn't match expected type ‘[((Int, Int), Maybe Piece)]’
                  with actual type ‘Maybe Piece’
    • In the second argument of ‘array’, namely
        ‘(Just (Piece White Pawn))’
      In the ‘board’ field of a record
      In the expression:
        Board
          {turn = White, castlingAvail = "", enpassant = Nothing,
           board = array (0, 0) (Just (Piece White Pawn))}

Which make sense because checking the array type

array :: Ix i => (i, i) -> [(i, e)] -> Array i e

so I try the following:

*MyLib Data.Array Chess> Board {
  turn = White
, castlingAvail = ""
, enpassant = Nothing
, board = array (0,0) [((0,0), (Just (Piece White Pawn)))]
}

which gives me this error:

<interactive>:108:78: error:
    • No instance for (Num (Int, Int)) arising from the literal ‘0’
    • In the expression: 0
      In the first argument of ‘array’, namely ‘(0, 0)’
      In the ‘board’ field of a record

Which leaves me very confused.. not quite sure why ghci interaction drives me to use a type different from what it appears in the source code of chesshs Board and why it anyway drives me to an error that I don't understand.

答案1

得分: 3

Array i e 是一种类型。它在一个不导出其数据构造函数的模块中定义,因此我们无法访问这些构造函数。这与 Maybe a 类型不同,我们可以访问 NothingJust 构造函数。

因此,要创建一个数组值,我们需要依赖模块导出的函数。确实有一个用于此目的的函数,名为 array。这个函数有时被称为“智能”构造函数,因为与常规构造函数不同,它在构造值之前执行一些检查。

无论如何,它的使用方式如下:

array (startPos, endPos)
      [ (startPos, value0), (nextPos, value1), ..., (endPos, valueLast) ]

我们提供一个包含第一个和最后一个有效数组索引/位置的对。然后,我们提供一个关联每个有效索引/位置与其值的列表。

在你的情况下,如果你的棋盘只包含位置 (0,0)(是否是这样?),那么它应该被创建为:

array ((0,0),(0,0)) [ ((0,0), Just (Piece White Pawn)) ]

如果你需要创建一个 8x8 的棋盘,你将需要一个更长的列表。

array ((0,0),(7,7)) [ ((0,0), Just (Piece White Pawn)) , ....
-- 添加所有其他位置,可能带有 Nothing 值

如果你只需要在大棋盘上放置一些棋子,那么可能更方便的方法是先创建一个空棋盘,然后用少数棋子更新它。例如:

let emptyB = array ((0,0),(7,7)) [ ((x,y), Nothing) | x<-[0..7], y<-[0..7] ]
    myB = emptyB // [ ((5,5), Just (Piece White Pawn)) ]
in ...

这里我使用了 // 运算符来创建一个包含与 emptyB 相同的棋子的新棋盘,除了列表中的那些位置和值。

英文:

Array i e is a type. It's defined in a module which does not export its data constructors, so we don't get access to those. This is unlike the Maybe a type for which we get access to the Nothing and Just constructors.

Hence, to create an array value we need to rely on the functions exported by the module. There is indeed a function for that, named array. This function is sometimes referred to as a "smart" constructor, since unlike a (regular) constructor it performs some sanity checks before constructing the value.

Anyway, it is meant to be used like this:

array (startPos, endPos)
      [ (startPos, value0), (nextPos, value1), ..., (endPos, valueLast) ]

We provide a pair with the first and last valid array indices/positions. We then provide a list of pairs. associating each valid index/position to its value.

In your case, if you board only contains position (0,0) (should it be so?) then it should be created as

array ((0,0),(0,0)) [ ((0,0), Just (Piece White Pawn)) ]

If instead you need to create a 8x8 board, you will need a longer list for that.

array ((0,0),(7,7)) [ ((0,0), Just (Piece White Pawn)) , ....
-- add all other positions, possibly with Nothing values

If you need to place only a few pieces in a large board, it might be more convenient to simply create an empty board and then update it with the few pieces. E.g.

let emptyB = array ((0,0),(7,7)) [ ((x,y), Nothing) | x&lt;-[0..7], y&lt;-[0..7] ]
    myB = emptyB // [ ((5,5), Just (Piece White Pawn)) ]
in ...

Here I used the // operator to create a new board with the same pieces as emptyB, except for those positions and values in the list.

huangapple
  • 本文由 发表于 2023年2月19日 19:28:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499802.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定