Haskell错误与类似复制的函数

jas*_*son 1 haskell replicate

我想写一个像这样的类似复制的函数:

repli"the"3 ="ttthhheee"和repli"jason"4 ="jjjjaaaassssoooonnnn"

这是我写的代码:

myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n)
Run Code Online (Sandbox Code Playgroud)

我得到的错误是这样的:

Couldn't match expected type `[a]' against inferred type `Char'
     Expected type: [[a]]
     Inferred type: [Char]
   In the first argument of `repli', namely `"jason"'
   In the expression: repli "jason" 3
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?谢谢.

mhw*_*bat 8

对于类型问题,这是一个非常有帮助的技巧.每当我对这样的消息感到困惑时,我会做以下事情:

  • 如果有问题的功能上有类型签名,请将其删除并查看是否有任何更改.如果它编译,请询问ghci类型是什么(使用:t).如果它没有编译,至少错误消息可能有足够的差异给你另一个线索.
  • 如果没有类型签名,请添加一个.即使它没有编译,错误消息可能会给你另一个线索.
  • 如果这没有帮助,那么暂时在函数中的每个表达式上添加类型声明.(通常你需要拆分一些表达式才能看到真正发生的事情.你可能还需要暂时启用ScopedTypeVariablespragma.)再次编译并检查错误消息.

最后一个是更多的工作,但我从这个练习中学到了很多东西.它通常指出了我认为类型与GHC认为类型之间存在不匹配的确切位置.

所以我们首先在代码中添加类型签名:

myrepli :: [a] -> Int -> [a]
myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli :: [a] -> Int -> [a]
repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n) -- triggers a compiler error
Run Code Online (Sandbox Code Playgroud)

啊,现在我们得到一个编译器错误:

amy.hs:9:27:
    Couldn't match expected type `a' with actual type `[a]'
      `a' is a rigid type variable bound by
          the type signature for repli :: [a] -> Int -> [a] at amy.hs:7:10
    In the first argument of `myrepli', namely `x'
    In the first argument of `(++)', namely `(myrepli x n)'
    In the expression: (myrepli x n) ++ (repli xs n)
Run Code Online (Sandbox Code Playgroud)

问题在于呼吁myrepli x n.该函数myrepli需要一个列表/字符串,但您传递的是一个字符.将最后一行更改为:

repli (x:xs) n = (myrepli [x] n) ++ (repli xs n)
Run Code Online (Sandbox Code Playgroud)

此时,您将在代码中发现其他错误.但是,不要修复你的代码,让我告诉你另一种方法:

repl (x:xs) n = (myReplicate x n) ++ (repl xs n)
repl [] _ = []

-- You could use the library function "replicate" here, but as a
-- learning exercise, we'll write our own.
myReplicate a n = take n (repeat a)
Run Code Online (Sandbox Code Playgroud)