首页 > 解决方案 > 错误处理:不正确的缩进 Haskell

问题描述

我在使用这个简单的代码时遇到了问题,因为它给了我一个错误,指出缩进不正确。

    opMe x y op = if op =="+" let x+y
    
    main=do
      op = "+"
      x = 8
      y = 10
      print(opMe (x, y, op))

我正在寻找的回报是 18。我收到的回报是 Incorrect Indention。

标签: haskell

解决方案


这里有很多问题。让我们一一修复它们:

 opMe x y op = if op =="+" let x+y

main=do
  op = "+"
  x = 8
  y = 10
  print(opMe (x, y, op))
q58566673.hs:3:1: error:
    parse error (possibly incorrect indentation or mismatched brackets)
  |
3 | main=do
  | ^

这里的问题实际上不是缩进。这是您的if语句没有thenor else,因此解析器期望它继续,而不是您开始新的声明。看起来你let在你打算使用的地方使用了then,所以让我们改变它。此外,else在 Haskell 中是强制性的。由于您还没有定义任何其他操作,所以我undefined现在将使用它,它可以让您的程序编译,但如果您最终在那里崩溃。

 opMe x y op = if op =="+" then x+y else undefined

main=do
  op = "+"
  x = 8
  y = 10
  print(opMe (x, y, op))
q58566673.hs:3:1: error: parse error on input ‘main’
  |
3 | main=do
  | ^^^^

还是不行。具有讽刺意味的是,现在的问题是缩进,但新的错误消息不再提到这种可能性。具体来说,问题是前导空格opMe。让我们删除它。

opMe x y op = if op =="+" then x+y else undefined

main=do
  op = "+"
  x = 8
  y = 10
  print(opMe (x, y, op))
q58566673.hs:4:6: error:
    parse error on input ‘=’
    Perhaps you need a 'let' in a 'do' block?
    e.g. 'let x = 5' instead of 'x = 5'
  |
4 |   op = "+"
  |      ^

在这里,GHC 的建议是正确的。您需要使用letdo块中声明变量。

opMe x y op = if op =="+" then x+y else undefined

main=do
  let op = "+"
  let x = 8
  let y = 10
  print(opMe (x, y, op))
q58566673.hs:5:11: error:
    • Ambiguous type variable ‘a0’ arising from the literal ‘8’
      prevents the constraint ‘(Num a0)’ from being solved.
      Relevant bindings include x :: a0 (bound at q58566673.hs:5:7)
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: 8
      In an equation for ‘x’: x = 8
      In the expression:
        do let op = "+"
           let x = 8
           let y = 10
           print (opMe (x, y, op))
  |
5 |   let x = 8
  |           ^

q58566673.hs:6:11: error:
    • Ambiguous type variable ‘b0’ arising from the literal ‘10’
      prevents the constraint ‘(Num b0)’ from being solved.
      Relevant bindings include y :: b0 (bound at q58566673.hs:6:7)
      Probable fix: use a type annotation to specify what ‘b0’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: 10
      In an equation for ‘y’: y = 10
      In the expression:
        do let op = "+"
           let x = 8
           let y = 10
           print (opMe (x, y, op))
  |
6 |   let y = 10
  |           ^^

q58566673.hs:7:3: error:
    • No instance for (Show
                         ((a0, b0, [Char]) -> [Char] -> (a0, b0, [Char])))
        arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    • In a stmt of a 'do' block: print (opMe (x, y, op))
      In the expression:
        do let op = "+"
           let x = 8
           let y = 10
           print (opMe (x, y, op))
      In an equation for ‘main’:
          main
            = do let op = ...
                 let x = ...
                 let y = ...
                 ....
  |
7 |   print(opMe (x, y, op))
  |   ^^^^^^^^^^^^^^^^^^^^^^

q58566673.hs:7:9: error:
    • No instance for (Num (a0, b0, [Char]))
        arising from a use of ‘opMe’
    • In the first argument of ‘print’, namely ‘(opMe (x, y, op))’
      In a stmt of a 'do' block: print (opMe (x, y, op))
      In the expression:
        do let op = "+"
           let x = 8
           let y = 10
           print (opMe (x, y, op))
  |
7 |   print(opMe (x, y, op))
  |         ^^^^^^^^^^^^^^^

这是一组非常无用的错误消息。这些错误如此无用的原因是它们是类型不匹配错误,但您没有为 指定类型opMe,因此 GHC 推断出一个比必要的多态性(因此给出更复杂的错误消息)的错误。让我们添加一个类型签名以获得更好的错误消息。

opMe :: Integer -> Integer -> String -> Integer
opMe x y op = if op =="+" then x+y else undefined

main=do
  let op = "+"
  let x = 8
  let y = 10
  print(opMe (x, y, op))
q58566673.hs:8:14: error:
    • Couldn't match expected type ‘Integer’
                  with actual type ‘(Integer, Integer, [Char])’
    • In the first argument of ‘opMe’, namely ‘(x, y, op)’
      In the first argument of ‘print’, namely ‘(opMe (x, y, op))’
      In a stmt of a 'do' block: print (opMe (x, y, op))
  |
8 |   print(opMe (x, y, op))
  |              ^^^^^^^^^^

清楚得多。这里的问题是你定义了你的函数curried(即,opMe x y op),但随后调用它就好像它是非curried(即,opMe (x, y, op))。要修复它,请选择其中一个并坚持下去。由于柯里化在 Haskell 中是惯用的,让我们继续吧:

opMe :: Integer -> Integer -> String -> Integer
opMe x y op = if op =="+" then x+y else undefined

main=do
  let op = "+"
  let x = 8
  let y = 10
  print(opMe x y op)
18

我们完成了!现在可以了。


推荐阅读