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

问题描述 投票:-1回答:1

我(非常)是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]’

我真的很感激任何想法,因为我已经挣扎了一段时间。

谢谢

list haskell cartesian-product
1个回答
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)],你希望它们作为字符串连接起来。这可以通过使用(:)而不是(,)来解决。

其次,由于一个列表是无限的,你需要将它作为你的“最外层循环”处理 - 如果它是一个内循环,它永远不会结束的事实意味着你的其他循环永远不会进展。当使用[]作为Applicative时,“外环”是你映射的第一个东西。

所以,我们可能会尝试:

(,) <$> (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"]
© www.soinside.com 2019 - 2024. All rights reserved.