Haskell: 非类型变量参数

Haskell: Non type-variable argument

大家好!我一直在学习 Haskell 到 this lecture series,我正在努力完成第 1 课的练习(链接在视频的描述中)。我在进行以下练习时遇到问题:

{- | Implement a function that takes a string, start and end positions
and returns a substring of a given string from the start position to
the end (including).

>>> subString 3 7 "Hello, world!"
"lo, w"

>>> subString 10 5 "Some very long String"
""

This function can accept negative start and end position. Negative
start position can be considered as zero (e.g. substring from the
first character) and negative end position should result in an empty
string.
-}

subString start end str = error "TODO"

我尝试的实现是这样的:

subString :: Int -> Int -> [a] -> [a]
subString start end str
    | end < 0 = []
    | start < 0 = subString 0 end str
    | otherwise = take ((end - start) + 1) (drop start str)

这给出了函数之前注释中包含的测试的预期结果(subString 3 7 "Hello, world!" 适当地给出了 "lo, w" 并且 subString 10 5 "Some very long String" 适当地给出了 "")。但是评论还说它应该适用于开始和结束的负值,这就是为什么我包括警卫来指定负数的预期行为。但是,当我在 ghci 中加载模块并调用 subString -1 4 "Hello, world" 时,出现此错误:

<interactive>:25:1: error:
    • Non type-variable argument
        in the constraint: Num (t -> [Char] -> Int -> Int -> [a] -> [a])
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall t a.
              (Num t, Num (t -> [Char] -> Int -> Int -> [a] -> [a]),
               Num (Int -> Int -> [a] -> [a])) =>
              Int -> Int -> [a] -> [a]

在大多数情况下,我发现 Haskell 错误消息比我 learned/tried 学习的其他语言更有帮助,但这条消息对我来说完全是胡说八道。这是怎么回事?

(注意:在我学习的这个阶段Haskell,我不在乎我写这个函数的方式是否不合常理。我只是想让它按预期工作。)

否定文字通常需要用括号括起来:

subString (-1) 4 "Hello, world"

否则 - 被解析为中缀减法运算符:

(subString) - (1 4 "Hello, world")

...很少进行类型检查,甚至很少有意义。作为推论,如果你想要一个省略 - 第一个参数的运算符部分,你不能使用语法 (-1);相反,使用 subtract 1(如有必要,可能用括号括起来)。