Debugging Haskell类型错误-由于使用“Print”而导致类型变量不明确`

Debugging Haskell类型错误-由于使用“Print”而导致类型变量不明确`,debugging,haskell,Debugging,Haskell,所以我试着写一点Haskell,我遇到了一个让我想把头撞到墙上的问题 printGrade points = case points of points | 0 <= points && points < 50 -> 5.0 points | 50 <= points && points < 54 -> 4.0 points | 54 <= points &&

所以我试着写一点Haskell,我遇到了一个让我想把头撞到墙上的问题

printGrade points = case points of            
    points | 0 <= points && points < 50 -> 5.0
    points | 50 <= points && points < 54 -> 4.0
    points | 54 <= points && points < 58 -> 3.7      
    points | 58 <= points && points < 62 -> 3.3
    points | 62 <= points && points < 66 -> 3.0
    points | 66 <= points && points < 70 -> 2.7
    points | 70 <= points && points < 74 -> 2.3
    points | 74 <= points && points < 78 -> 2.0
    points | 78 <= points && points < 82 -> 1.7
    points | 82 <= points && points < 86 -> 1.3
    points | 86 <= points && points < 100 -> 1.0

note a b c d = 
            if d > 100 || c > 20
            then return "Wrong input"
            else if a == False || b == False 
            then printGrade d
            else printGrade (c + d) 
printGrade点=案例点
点数| 0.5.0
50分4.0分
第54点3.7
第58点3.3
得分| 62 3.0
第66点2.7
第70点2.3
积分| 74 2.0
第78点1.7
第82点1.3
积分| 86 1.0
注a b c d=
如果d>100 | c>20
然后返回“输入错误”
如果a==False | | b==False,则为else
然后是d级
其他打印级别(c+d)
当我尝试运行代码时,它编译时没有问题,但实际调用该函数会导致此错误

<interactive>:91:1: error:
• Ambiguous type variable ‘m0’ arising from a use of ‘print’
  prevents the constraint ‘(Show (m0 [Char]))’ from being solved.
  Probable fix: use a type annotation to specify what ‘m0’ should be.
  These potential instances exist:
    instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
    instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
    instance (Show a, Show b, Show c) => Show (a, b, c)
      -- Defined in ‘GHC.Show’
    ...plus 13 others
    ...plus two instances involving out-of-scope types
    (use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
:91:1:错误:
•由于使用“打印”而导致类型变量“m0”不明确
阻止解决约束“(显示(m0[Char])”。
可能的修复:使用类型注释指定“m0”应该是什么。
这些潜在的例子存在:
实例Show a=>Show(可能是a)--在“GHC.Show”中定义
实例(Show a,Show b)=>Show(a,b)--在“GHC.Show”中定义
实例(Show a,Show b,Show c)=>Show(a,b,c)
--在“GHC.Show”中定义
…加上其他13个
…加上两个涉及范围外类型的实例
(使用-fprint潜在实例查看所有实例)
•在交互式GHCi命令的stmt中:打印它

我知道这与返回“错误输入”有关,但我不知道如何解决这个问题,因为我必须在某个时候打印出字符串。(我试过show/print/putStrLn,这导致了另一个错误)

通常,从Haskell开始的人都会使用这个函数,因为在命令式世界中,几乎所有的[命令式]编程语言都会为
return
关键字分配几乎相同的语义。然而,在Haskell中,
return
是一个函数(不是关键字),它用于monad的上下文中。虽然monad功能非常强大,但我建议在使用
return
之前先看看这个结构是如何工作的。一个提示:它并不像在命令式世界中那样工作

我们可以删除
return
函数,如:

note a b c d = 
    if d > 100 || c > 20
        then "Wrong input"
        else if a == False || b == False 
            then printGrade d
            else printGrade (c + d)
但是我们得到了一个新的错误:

<interactive>:20:18: error:
    • Could not deduce (Fractional [Char])
        arising from a use of ‘printGrade’
      from the context: (Num a, Ord a)
        bound by the inferred type of
                 note :: (Num a, Ord a) => Bool -> Bool -> a -> a -> [Char]
        at <interactive>:(16,1)-(21,35)
    • In the expression: printGrade d
      In the expression:
        if a == False || b == False then
            printGrade d
        else
            printGrade (c + d)
      In the expression:
        if d > 100 || c > 20 then
            "Wrong input"
        else
            if a == False || b == False then
                printGrade d
            else
                printGrade (c + d)
现在程序将编译,但它相当不美观。例如,在
printGrade
函数中使用
case
,但实际上不执行任何模式匹配。我们可以使用防护装置,例如:

grade :: (Num a, Ord a, Fractional b) => a -> b
grade points | points < 0 = error "too small"
             | points < 50 = 5.0
             | points < 54 = 4.0
             | points < 58 = 3.7      
             | points < 62 = 3.3
             | points < 66 = 3.0
             | points < 70 = 2.7
             | points < 74 = 2.3
             | points < 78 = 2.0
             | points < 82 = 1.7
             | points < 86 = 1.3
             | points < 100 = 1.0
             | otherwise = error "too large"

通常,以Haskell开头的人会使用该函数,因为在命令式世界中,几乎所有的[命令式]编程语言都会为
return
关键字分配几乎相同的语义。然而,在Haskell中,
return
是一个函数(不是关键字),它用于monad的上下文中。虽然monad功能非常强大,但我建议在使用
return
之前先看看这个结构是如何工作的。一个提示:它并不像在命令式世界中那样工作

我们可以删除
return
函数,如:

note a b c d = 
    if d > 100 || c > 20
        then "Wrong input"
        else if a == False || b == False 
            then printGrade d
            else printGrade (c + d)
但是我们得到了一个新的错误:

<interactive>:20:18: error:
    • Could not deduce (Fractional [Char])
        arising from a use of ‘printGrade’
      from the context: (Num a, Ord a)
        bound by the inferred type of
                 note :: (Num a, Ord a) => Bool -> Bool -> a -> a -> [Char]
        at <interactive>:(16,1)-(21,35)
    • In the expression: printGrade d
      In the expression:
        if a == False || b == False then
            printGrade d
        else
            printGrade (c + d)
      In the expression:
        if d > 100 || c > 20 then
            "Wrong input"
        else
            if a == False || b == False then
                printGrade d
            else
                printGrade (c + d)
现在程序将编译,但它相当不美观。例如,在
printGrade
函数中使用
case
,但实际上不执行任何模式匹配。我们可以使用防护装置,例如:

grade :: (Num a, Ord a, Fractional b) => a -> b
grade points | points < 0 = error "too small"
             | points < 50 = 5.0
             | points < 54 = 4.0
             | points < 58 = 3.7      
             | points < 62 = 3.3
             | points < 66 = 3.0
             | points < 70 = 2.7
             | points < 74 = 2.3
             | points < 78 = 2.0
             | points < 82 = 1.7
             | points < 86 = 1.3
             | points < 100 = 1.0
             | otherwise = error "too large"

为什么您在这里使用
案例
,但只使用防护装置?哈哈哈,我不知道何时删除案例,但它根本不起作用,不幸的是,这个错误经常出现
return
不是Haskell中的关键字:它是一个用于monad的函数。因此,我建议您不要使用它,除非您知道自己在做什么。我可以使用什么来代替return来打印字符串而不会导致此错误?您应该从类型开始编写这些函数。如果返回类型是,比如说,
Double
,则不能返回字符串(当然也不能返回monad中的字符串,如
return“abc”
)。如果你想出错,你可以使用
If。。。然后是2.71 else错误“message”
,但请理解,此错误在计算时会使程序崩溃,调用方将无法捕获错误并处理它。有时候这就足够了。表达式
error.”“
适合任何类型。为什么在这里使用
case
,而只使用防护装置?哈哈哈,我不知道何时删除case,它根本不起作用,不幸的是,这个错误经常出现
return
不是Haskell中的关键字:它是一个用于monad的函数。因此,我建议您不要使用它,除非您知道自己在做什么。我可以使用什么来代替return来打印字符串而不会导致此错误?您应该从类型开始编写这些函数。如果返回类型是,比如说,
Double
,则不能返回字符串(当然也不能返回monad中的字符串,如
return“abc”
)。如果你想出错,你可以使用
If。。。然后是2.71 else错误“message”
,但请理解,此错误在计算时会使程序崩溃,调用方将无法捕获错误并处理它。有时候这就足够了。表达式
error..“
适用于任何类型。