1

I want to write a replicate-like function that works like this :

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

Here is the code that I wrote :

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)

The error I get is this :

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

How can I fix this? Thanks.

4

2 回答 2

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

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

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)

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

repli (x:xs) n = (myrepli [x] n) ++ (repli xs n)

此时,您会在代码中发现其他错误。但是,与其修复您的代码,让我向您展示另一种方法:

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)
于 2014-02-18T12:20:35.620 回答
3

myrepli期待一个列表和一个整数。但是, 的定义用 来repli调用它x,它是一个项目,而不是项目列表

我想您要么想更改myrepli为将单个项目作为参数,要么您想更改repli为 pass[x]而不是 just x。(我建议前者而不是后者。)

于 2014-02-18T12:17:11.067 回答