如何组合 haskell 中两个字符串中的字母

How to combine the letters in two strings in haskell

我正在学习 Haskell 并遵循 http://learnyouahaskell.com/starting-out 上的指南。我在显示的位置:

ghci> let nouns = ["hobo","frog","pope"]  
ghci> let adjectives = ["lazy","grouchy","scheming"]  
ghci> [adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]  
["lazy hobo","lazy frog","lazy pope","grouchy hobo","grouchy frog",  
"grouchy pope","scheming hobo","scheming frog","scheming pope"]   

我想要实现的,它是类似的东西,但是结合了两个字符串中包含的字母,并且由于字符串基本上是 Haskell 中的 char 列表,这就是我尝试的:

 [x ++ ' ' ++ y | x <- "ab", y <- "cd"]

但是编译器在抱怨:

Prelude> [y ++ ' ' ++ y | x <- "abd", y <- "bcd"]

<interactive>:50:2:
    Couldn't match expected type ‘[a]’ with actual type ‘Char’
    Relevant bindings include it :: [[a]] (bound at <interactive>:50:1)
    In the first argument of ‘(++)’, namely ‘y’
    In the expression: y ++ ' ' ++ y

<interactive>:50:7:
    Couldn't match expected type ‘[a]’ with actual type ‘Char’
    Relevant bindings include it :: [[a]] (bound at <interactive>:50:1)
    In the first argument of ‘(++)’, namely ‘' '’
    In the second argument of ‘(++)’, namely ‘' ' ++ y’
    In the expression: y ++ ' ' ++ y

<interactive>:50:14:
    Couldn't match expected type ‘[a]’ with actual type ‘Char’
    Relevant bindings include it :: [[a]] (bound at <interactive>:50:1)
    In the second argument of ‘(++)’, namely ‘y’
    In the second argument of ‘(++)’, namely ‘' ' ++ y’

我做了很多尝试,例如将表达式括在方括号中以获得列表,将 space 更改为字符串而不是字符...我怎样才能让它工作?

谢谢

++ 仅适用于列表,但 xy 仅适用于 Char。毕竟,它们是来自 String (= [Char]) 的元素,而 LYAH 示例具有 Char 列表的列表:[String] = [[Char]]:

-- [a] -> [a] -> [a]
-- vv     vv
[y ++ ' ' ++ y | x <- "abd", y <- "bcd"]
--           ^   ^           ^
--           Char           Char

-- vs

--                                        [String]          [String]
--                                       vvvvvvvvvv          vvvvv
[adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]  
-- ^^^^^^^           ^^^^
-- String           String

相反,使用 (:) 将字符相互转换到空列表中:

[x : ' ' : y : [] | x <- "abd", y <- "bcd"]
x ++ ' ' ++ y

这里的实际问题是,您正在尝试连接三个字符,并使用仅为项目列表定义的函数。 ++ 实际上会连接两个列表,而不是两个单独的项目并给出一个列表。

  1. 因此,您可以通过将所有字符转换为字符串来修复您的程序,就像这样

    > [[x] ++ " " ++ [y] | x <- "ab", y <- "cd"]
    ["a c","a d","b c","b d"]
    

    注意 " ",而不是 ' '。因为 " " 表示只有 space 个字符的字符串,而 ' ' 表示只有 space 个字符。

  2. 或者,将y转换为字符串,使用cons运算符和' ',并将其连接到x转换为字符串, 像这样

    > [[x] ++ (' ' : [y]) | x <- "ab", y <- "cd"]
    ["a c","a d","b c","b d"]
    
  3. 或者,更简单直观,,创建一个字符列表,像这样

    > [[x, ' ', y] | x <- "ab", y <- "cd"]
    ["a c","a d","b c","b d"]
    

注意:[] 包裹一个字符使其成为一个字符列表,其中只有一个字符。它基本上变成了一个字符串。