2014-02-18 101 views
1

我想写复制般的功能是这样的哈斯克尔错误:与复制般的功能

repli "the" 3 = "ttthhheee" and 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) 

错误我得到的是:

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 

我该如何解决这个问题?谢谢。

+0

'repli xs n = concatMap(replicate n)xs = flip(concatMap。replicate)xs n'。 –

回答

3

myrepli期待列表和一个整数。然而,repli的定义将其与x调用,这是一个项目,而不是列表的项目。

我想你要么要换myrepli采取单个项目作为参数,要更改repli通过[x]而不是仅仅x。 (我会建议前者而不是后者。)

8

对于类型问题,这里有一个技巧,帮助我非常。每当我完全被这样的消息困惑时,我会执行以下操作:

  • 如果在相关函数上存在类型签名,请将其删除并查看是否有任何更改。如果编译,请问ghci是什么类型(使用:t)。如果它不编译,至少错误信息可能会有所不同,给你另一个线索。
  • 如果没有类型签名,请添加一个。即使它不编译,错误消息可能会给你另一个线索。
  • 如果这没有帮助,那么临时添加函数中每个表达式的类型声明。 (通常情况下,您需要分解一些表达式以查看实际情况,您可能还需要暂时启用ScopedTypeVariables编译指示。)再次编译并检查错误消息。

最后一个是更多的工作,但我从这个练习中学到了很多东西。它通常会指出我认为类型与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) 
+0

较短的最终解决方案:'repl xs n = xs >> =(replicate n)'(如果需要,可以用'myReplicate'替换'replicate')。 – Nicolas

+1

或者'repl xs n = concatMap(replicate n)xs' – Nicolas

+0

或者您可以使用免费版的点'repl =(= <<)。如果你交换参数的顺序(即'repl 3“,''),那么'replicate'。 – bheklilr