Haskell - 使用“最小”时没有(Ord Pos)的实例

时间:2018-01-08 13:33:51

标签: haskell

我目前在使用我的数据类型处理这段代码时遇到了一些问题。我使用

时工作正常

type Pos = (Int, Int)

然而我需要使用

data Pos = Pos (Int, Int) deriving (Show, Eq)

对于其余的代码,我已经能够将其更改为(Pos(x,y)),但是对于这一个函数,它正在抛出此错误消息。

* No instance for (Ord Pos) arising from a use of `minimum'
* In the second argument of `(.)', namely `minimum'
  In the expression: snd . minimum
  In the expression:
    snd . minimum $ [(score p, p) | p <- allBlanks puzzle]

这是我的功能:

blankX2 puzzle = 
  snd
  . minimum $ 
  [(score p, p) | p <- allBlanks puzzle] where
    score (Pos(y,x)) = rowScore y + colScore x + sqScore (div x 3, div y 3)
    rowScore r = blanksInBlock (row r puzzle)
    colScore c = blanksInBlock (column c puzzle)
    sqScore sq = blanksInBlock (square sq puzzle)

2 个答案:

答案 0 :(得分:4)

首先说的是,尽管与你的问题无关:不要在data中包装元组,最好使它们成为数据类型的字段。在这种情况下,您还希望使字段严格,以提高性能:

data Pos = Pos { xPosition, yPosition :: !Int }
  deriving (Show, Eq)

现在,您还需要一个Ord实例。嗯,最简单的方法是将其添加到deriving列表中!

data Pos = Pos { xPosition, yPosition :: !Int }
  deriving (Show, Eq, Ord)

或者,您也可以自己定义它,也许是因为您需要与标准排序不同的顺序。要做到这一点,你要写

instance Ord Pos

然后编译器会抱怨:

warning: [-Wmissing-methods]
    • No explicit implementation for
        either ‘compare’ or ‘<=’
    • In the instance declaration for ‘Ord Pos’
  |
3 | instance Ord Pos
  |          ^^^^^^^

好的,所以我们最好添加其中一种方法。 <=更容易理解,但compare更直接涵盖所有情况,因此建议使用。要查看您需要做什么,请从存根开始:

instance Ord Pos where
  compare = _

GHC回答:

• Found hole: _ :: Pos -> Pos -> Ordering
• In the expression: _
  In an equation for ‘compare’: compare = _
  In the instance declaration for ‘Ord Pos’
• Relevant bindings include
    compare :: Pos -> Pos -> Ordering
      (bound at /tmp/wtmpf-file6330.hs:4:3)

因此,您需要将compare实现为具有该签名的函数。

答案 1 :(得分:3)

您的Pos数据类型必须是Ord类型类的实例才能由minimum使用。该类型类提供比较函数,例如<。只需在OrdShow之后添加Eq即可让GHC自动为您提供必要的功能。