首页 > 解决方案 > Haskell 错误 - 没有由文字“1”引起的 (Num a) 实例

问题描述

我正在尝试创建一个在给定列表中的每个条目之前添加 1 的函数。我还没有完全掌握 Haskell 的语法,我想知道这段代码有什么问题。例如,我希望它返回列表 [1,1,1,2,1,3]

ins1 :: [a] -> [a]
ins1 [x] = [x]
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)

main = print(ins1 [1,2,3])

我得到错误:

• No instance for (Num a) arising from the literal ‘1’
  Possible fix:
    add (Num a) to the context of
      the type signature for:
        ins1 :: [a] -> [a]
• In the expression: 1
  In the first argument of ‘(++)’, namely ‘[1]’
  In the expression: [1] ++ [x] ++ ins1 (xs)
<interactive>:3:1: error:
• Variable not in scope: main
• Perhaps you meant ‘min’ (imported from Prelude)

标签: listhaskell

解决方案


就像错误所说的那样,您使用ins1,然后编写[1] ++ [x] ++ ....

Now1是一个数字文字,因此它可以采用所有数字类型。因此1有类型Num b => b,结果[1]有类型Num b => [b]

稍后您将列表附加到x和递归,因此我们现在知道a ~ ba并且b是相同的类型)。所以我们必须在签名中添加一个类型约束a

ins1 :: Num a => [a] -> [a]
ins1 [x] = [x]
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)

这解决了编译错误,但可能不会生成你想要的。由于现在没有空列表的情况。实际上,[x]模式和模式都适用于分别与仅具有一个元素和至少(x:xs)一个元素的列表匹配的列表。

因此,我认为您的第一个子句实际上应该与空列表匹配:

ins1 :: Num a => [a] -> [a]
ins1 [] = []
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)

第二个子句也有一个低效率:你追加到一个元素的列表,所以我们可以在这里使用“ cons ”数据构造函数(:)

ins1 :: Num a => [a] -> [a]
ins1 [] = []
ins1 (x:xs) = 1 : x : ins1 xs

这将为原始列表中的每个元素1插入一个,因此:

Prelude> ins1 [1, 4, 2, 5]
[1,1,1,4,1,2,1,5]

推荐阅读