没有因使用句法否定而产生的 (Num (Int -> Int)) 实例

mat*_*att 2 recursion haskell partial-application

我编写了以下 Haskell 代码来返回 [[Int]] 的主要和次要对角线

getDiagonal' :: [[Int]] -> Int -> (Int -> Int) -> [Int]
getDiagonal' [] _ _ = []
getDiagonal' (x:xs) i fn = i' : getDiagonal' xs (fn i) fn
  where i' = head $ drop i x

getPrimaryDiagonal :: [[Int]] -> [Int]
getPrimaryDiagonal x = getDiagonal' x 0 (+1)

getSecondaryDiagonal :: [[Int]] -> [Int]
getSecondaryDiagonal x = getDiagonal' x ((length x) - 1) (+(-1))
Run Code Online (Sandbox Code Playgroud)

但是,我会认为最后一行可能是以下内容,使用(-)(+)

getSecondaryDiagonal x = getDiagonal' x ((length x) - 1) (-1)
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,当我这样做时,我得到

Main.hs:27:59: error:
    • No instance for (Num (Int -> Int))
        arising from a use of syntactic negation
        (maybe you haven't applied a function to enough arguments?)
    • In the third argument of ‘getDiagonal'’, namely ‘(- 1)’
      In the expression: getDiagonal' x ((length x) - 1) (- 1)
      In an equation for ‘getSecondaryDiagonal’:
          getSecondaryDiagonal x = getDiagonal' x ((length x) - 1) (- 1)
Run Code Online (Sandbox Code Playgroud)

为什么会(-)产生那个错误?

Wil*_*sem 5

(-1)被解释为负数,据我所知,这是对非二进制运算符的唯一例外。(-1)因此不是一个减去 1 的函数。

您可以subtract :: Num a => a -> a -> a 为此使用:

getSecondaryDiagonal x = getDiagonal' x ((length x) - 1) (subtract 1)
Run Code Online (Sandbox Code Playgroud)

或者您可以使用flip :: (a -> b -> c) -> b -> a -> c which 是如何subtract实现的:

getSecondaryDiagonal x = getDiagonal' x ((length x) - 1) (flip (-) 1)
Run Code Online (Sandbox Code Playgroud)

  • “(-)”部分的这种奇怪行为有时需要的另一个函数是“negate”,当您需要一元否定作为函数值而不是立即将其应用于文字数字时,该函数很有用。 (3认同)