我是Haskell的初学者.我正在尝试创建一个具有两个参数的函数:字符和字符串.该函数应该遍历字符串并检查给定的字符是否在字符串中,然后返回表示字符串中字符位置的整数列表.
我的代码是:
tegnPose :: Char -> String -> [Int]
tegnPose c [] = []
tegnPose c (x:xs) = [if not (xs !! a == c)
then [a] ++ tegnPose c xs
else tegnPose c xs |a <- [0.. length xs - 1]]
Run Code Online (Sandbox Code Playgroud)
这是具有列表理解的递归函数.
我得到的错误:
Uke4.hs:14:7: error:
* Couldn't match expected type `Int' with actual type `[Int]'
* In the expression: [a] ++ tegnPose c xs
In the expression:
if not (xs !! a == c) then [a] ++ tegnPose c xs else tegnPose c xs
In the expression:
[if not (xs !! a == c) then
[a] ++ tegnPose c xs
else
tegnPose c xs |
a <- [0 .. length xs - 1]]
|
14 | then [a] ++ tegnPose c xs
| ^^^^^^^^^^^^^^^^^^^^
Uke4.hs:15:7: error:
* Couldn't match expected type `Int' with actual type `[Int]'
* In the expression: tegnPose c xs
In the expression:
if not (xs !! a == c) then [a] ++ tegnPose c xs else tegnPose c xs
In the expression:
[if not (xs !! a == c) then
[a] ++ tegnPose c xs
else
tegnPose c xs |
a <- [0 .. length xs - 1]]
|
15 | else tegnPose c xs |a <- [0.. length xs - 1]]
Run Code Online (Sandbox Code Playgroud)
我不明白不匹配是如何发生的,因为递归函数应该只是运行.
这就是错配发生的原因.首先,请注意返回类型列表的列表推导[a]必须生成类型的元素a,因此您需要以下匹配:
example :: [Int]
-- .-- the final value is "[Int]"
-- |
example = [ 2+x*y | x <- [1..10], y <- [1..5], x < y]
-- ^^^^^
-- |
-- `- therefore, this must be "Int"
Run Code Online (Sandbox Code Playgroud)
在您的示例中,类型签名tegnPose意味着列表推导必须返回一个[Int],但表达式生成列表元素,即:
if ... then [a] ++ tegnPose c xs else tegnPose c cx
Run Code Online (Sandbox Code Playgroud)
显然没有Int按照预期的方式返回原状.
所述第一错误消息,指示实际类型的子表达式的[a] ++ tegnPos c xs是[Int]不匹配的整个的结果的预期类型if .. then .. else应该有型表达Int.
如果我没有理解你的问题(即,在一个字符串,以便返回字符的每次出现的整数位置的列表tegnPose 'a' "abracadabra"回报[0,3,5,7,10],那么你应该要么使用递归或列表理解,但不能同时使用.
注意非递归列表理解:
tegnPose c xs = [a | a <- [0..length xs - 1]
Run Code Online (Sandbox Code Playgroud)
几乎做你想要的.所有缺少的是测试条件以查看位置a上的角色是否为a c.如果您不知道在列表推导中使用"警卫",请查阅它.
或者,没有列表理解的递归函数:
tegnPose c (x:xs) = if (x == c) then ??? : tegnPose c xs
else tegnPose c xs
tegnPose _ [] = []
Run Code Online (Sandbox Code Playgroud)
也几乎可以做你想要的,除了它不明显是什么代替???返回一个表示当前位置的数字.如果您使用额外参数编写递归版本:
tp n c (x:xs) = if (x == c) then n : tp (???) c xs
else tp (???) c xs
tp _ _ [] = []
Run Code Online (Sandbox Code Playgroud)
你可以定义:
tegnPose c xs = tp 0 c xs
Run Code Online (Sandbox Code Playgroud)
然后你会更接近,只要你能找出n应该代替的新价值???.
更多标准的Haskell解决方案可能涉及拉链等内容:
> zip [0..] "abracadabra"
[(0,'a'),(1,'b'),(2,'r'),...]
Run Code Online (Sandbox Code Playgroud)
和过滤器:
> filter (\(i,c) -> c == 'a') $ zip [0..] "abracadabra"
[(0,'a'),(3,'a'),...]
Run Code Online (Sandbox Code Playgroud)
和地图:
> map fst $ filter (\(i,c) -> c == 'a') $ zip [0..] "abracadabra"
[0,3,5,7,10]
Run Code Online (Sandbox Code Playgroud)
或者寻找能够Data.List达到你想要的功能:
> elemIndices 'a' "abracadabra"
[0,3,5,7,10]
Run Code Online (Sandbox Code Playgroud)