部分应用函数并在之后编写它们

时间:2016-03-31 14:24:31

标签: haskell composition chess

我目前正在Haskell的一个国际象棋游戏中工作。这是我的函数,当你为它提供正确的参数以在王牌上进行铸造时,评估为True。 (问题出在第1部分和第2部分,请看评论)。我尝试使用函数组合来找到一个更简洁的解决方案,但它并没有真正解决我的问题。如果有人能看一眼我做了什么并解释我哪里出错了,我会很高兴...非常感谢提前

shortCastlingWhite :: Int -> Int -> GameState -> Bool
shortCastlingWhite start end state@(board,_) = 
(board !! 95 == 10) &&                              -- on 95=(e,1) is a white King
(board !! 98 == 11) &&                              -- on 98=(h,8) is a white Rook
(start == 95 && end == 97) &&                       -- move from (e,1) to 97=(g,1)
(not $ (wasMoved state 95 || wasMoved state 98) &&  -- King and Tower weren't moved until now
(not $ (indexOccupied 96 state ||                       -- part 1 !! 96=(f,1) and (g,1) are unoccupied
(indexOccupied 97 state) ||                         -- part 1
(isThreatenedBy Black 95 state) ||                  -- part 2 !! neither (e,1) nor (f,1) or (g,1) are threatened by Black Figures
(isThreatenedBy Black 96 state) ||                  -- part 2
(isThreatenedBy Black 97 state)))                   -- part 2

这是使用函数的类型签名

isThreatenedBy :: Colour -> GameState -> Int -> Bool
wasMoved :: GameState -> Int -> Bool

我想将非常详细的第1部分和第2部分重写为:

all (swap indexUnoccupied state) [96,97] && 
(all ((not.isThreatenedBy) Black state) [95,96,97]) && 
(all ((not.wasMoved) state) [95,98])  
    where swap f a b = f b a
--

但是我无法解决错误消息:

newchess.hs:240:181:
    Couldn't match expected type `GameState -> a0 -> Bool`
                with actual type `Bool`
    The function `not . isThreatenedBy` is applied to two arguments,
    but its type `Colour -> Bool` has only one
    In the first argument of `all`, namely
      `((not . isThreatenedBy) Black state)`
    In the first argument of `(&&)', namely
    `(all ((not . isThreatenedBy) Black state) [95, 96, 97])`

isThreatenedBy :: Color - > GameState - > Int - >布尔

当我没有作出并且被打破时,我应该得到 类型为

的函数f = (not . isThreatenedBy)

f :: Colour -> GameState -> Int -> Bool

但我觉得我觉得Colour -> Bool之类的东西。 然后我部分应用Color和GameState的值 结果函数f'的类型应为

f' :: Int -> Bool

然后我将它映射到列表[95,96,97]并查看 如果每个元素都通过f'

满足all

左右计划......

newchess.hs:240:186:
    Couldn't match type `GameState -> Int -> Bool` with `Bool`
    Expected type: Colour -> Bool
      Actual type: Colour -> GameState -> Int -> Bool
    Probable cause: `isThreatenedBy` is applied to too few arguments
    In the second argument of `(.)`, namely `isThreatenedBy`
    In the expression: not . isThreatenedBy

奇怪的是(not。wasMoved)在error1中应用了太多的参数 并且可能在错误2中太少,但是 我无法移动括号内的列表元素, 否则我可以回到我开始的那一点

newchess.hs:240:238:
    Couldn't match expected type `a1 -> Bool` with actual type `Bool`
    Possible cause: `not . wasMoved` is applied to too many arguments
    In the first argument of `all`, namely `((not . wasMoved) state)`
    In the second argument of `(&&)`, namely
      `(all ((not . wasMoved) state) [95, 98])`

与错误1中的上述相同(只是这次使用wasMoved)

newchess.hs:240:243:
    Couldn't match type `Int -> Bool' with `Bool`
    Expected type: GameState -> Bool
      Actual type: GameState -> Int -> Bool
    Probable cause: `wasMoved` is applied to too few arguments
    In the second argument of `(.)`, namely `wasMoved`
    In the expression: not . wasMoved
Failed, modules loaded: none.

如错误2我认为

2 个答案:

答案 0 :(得分:3)

我可能会误解这一点,但看看这个。这不起作用:

Prelude> let f = (abs . (+))

<interactive>:11:5:
    Non type-variable argument in the constraint: Num (a -> a)
    (Use FlexibleContexts to permit this)
    When checking that ‘f’ has the inferred type
      f :: forall a. (Num a, Num (a -> a)) => a -> a -> a

不进行类型检查。原因是(.)函数将两个函数作为参数,其中这两个函数各占一个参数。在此示例中,(+)函数采用两个参数,因此类型错误。这有效:

Prelude> let f = (abs . (+ 3))

因为我将函数转换为只接受一个参数的函数。您的isThreatenedBy功能可以通过相同的方式更改:

(all (not . (isThreatenedBy Black state)) [95,96,97])

不确定这是否真的是你的根本问题,但试试看。

答案 1 :(得分:3)

让我们从自定义谓词开始:

isThreatenedBy :: Colour -> State -> Position -> Bool

我们当然可以这样写:

isThreatenedBy :: Colour -> (State -> (Position -> Bool))

现在,应该清楚为什么这个功能不能由not组成,Bool -> Bool本身就是(.) :: (b -> c) -> (a -> b) -> a -> c

:: not . isThreatenedBy

-- from `not`:
b ~ Bool
c ~ Bool 

-- from `isThreatenedBy:
a ~ Colour
b ~ (State -> (Position -> Bool))

现在替代:

b

显然all . map not . map (isThreatenedBy color state) $ [95,96,97] 在这里不匹配。

现在你可以做的是将作品推到第一个应用程序之外(dvaergiller在他的回答中做了什么),或者引入了额外的步骤:

none = and . map not

这可能与典型的map-reduce模式形成对比,但我个人认为它更具可读性。

或者,帮助:

none = not . or

(或者,正如@FrerichRaabe所建议并由Augustus De Morgan慷慨提供):

[Route("api/myApi")]
 public HttpStatusCode Post(SomeModelType modelObject)
{ ... }

可以使这更清楚。