不同类型的两个列表的笛卡尔积(Haskell)

时间:2019-04-04 19:43:12

标签: list haskell cartesian-product

我(非常)是Haskell的新手,我试图解决我认为简单的问题:

我想创建两个不同类型的列表的笛卡尔积的列表:一个包含字符,一个包含整数。

   ['A','B','C']

和无限列表:

    [1..]

我正在尝试输出一个我的字母都带有数字后缀的输出:例如。

    ["A1", "B1", "C1", "A2", "B2"..]

我一直在尝试使用在线阅读的内容进行尝试,但是我一直在努力。据我了解,我想使用“ show”将整数列表转换为字符串。我的代码如下:

    combinations xs cs = (,) <$> xs (show <$> cs)

xs和cs在我的函数中分别以['A','B','C']和[1 ..]传递。

但是我收到此错误:

   Couldn't match expected type ‘[String] -> [a0]’
              with actual type ‘[Char]’

我一直很努力,很感谢任何想法。

谢谢

1 个答案:

答案 0 :(得分:3)

(,) <$> xs (show <$> cs)

解析为

(,) <$> (xs (show <$> cs))

请注意,这里您以xs作为参数调用show <$> cs作为函数。可能不正确:xs是一个字符串!

由于您似乎试图以应用程序风格进行编程,因此您可能打算编写某种形式的

f <$> a <*> b

就您而言,

f = (,)
a = xs
b = show <$> cs

所以,你打算写:

(,) <$> xs <*> (show <$> cs)

这有点接近您想要的内容,但是存在一些问题。首先,它的类型为[(Char, String)],在这里您希望它们以字符串形式连接。可以通过使用(:)而不是(,)来解决。

第二,由于一个列表是无限的,因此您需要将其作为“最外层循环”进行处理-如果它是一个内层循环,那么它永无止境的事实将意味着您的其他循环永远不会进行。将[]用作适用语时,“外部循环”是映射的第一件事。

因此,我们可以尝试:

(,) <$> (show <$> cs) <*> xs

请注意,我已经回到(,)了一段时间以突出显示某些内容:

Prelude> take 5 $ (,) <$> (show <$> cs) <*> xs
[("1",'A'),("1",'B'),("1",'C'),("2",'A'),("2",'B')]

现在,我们得到了所需的对,但是(:)将不再适用于它们,因为它们的顺序不正确。因此,您需要使用一个不同的函数,例如(:),但该函数以另一顺序使用其参数。令人高兴的是,产生这样的函数很容易:它只是flip (:)

Prelude> take 5 $ (flip (:)) <$> (show <$> cs) <*> xs
["A1","B1","C1","A2","B2"]