Haskell类型不匹配Int和[Int]

1 int haskell types mismatch

我是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)

我不明白不匹配是如何发生的,因为递归函数应该只是运行.

K. *_*uhr 5

这就是错配发生的原因.首先,请注意返回类型列表的列表推导[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)