[英]Haskell, List as input for a function, How?
I've been given the following question in my coursework; 在我的课程中,我曾被问到以下问题;
Define a function 定义功能
flatten :: [(Char,Int)] -> String
that flattens a list of pairs of characters and digits to a string. 将字符和数字对的列表展平为字符串。 For example:
例如:
flatten [('a',5),('b',4),('c',2)]
"a5b4c2"
flatten [('d',9),('d',3)]
"d9d3"
My problem is that whenever I attempt to define this function i get a type error relating the the [(Char, Int)]
input. 我的问题是,每当我尝试定义此函数时,我都会得到与
[(Char, Int)]
输入有关的类型错误。 For example; 例如;
Couldn't match type '(Char, Int)' with '[Char]' Expected type: [[Char]] Actual type: [(Char, Int)]
I've tried more ways of writing this definition in more ways than I can count, so I don't have any particular code to show, or any particular error ( I kept getting different ones...so many). 我尝试了更多的方式来编写此定义,而不用数数,因此我没有要显示的任何特定代码或任何特定的错误(我不断得到不同的代码...太多了)。 All i have so far is;
到目前为止,我所拥有的只是;
flatten :: [(Char, Int)] -> String
flatten [] = []
i figure my next line should go something like; 我认为我的下一行应该是这样的;
flatten ???? = concat (????)
but I have no idea what to put in place of these question marks and Google search/class notes give no examples to follow. 但我不知道该用什么代替这些问号,并且Google搜索/课程注释中没有提供任何示例。 any ideas?
有任何想法吗?
Well it is clear that in the case the list is not empty, it is of the form ((ca,cb):cs)
with ca
the Char
, cb
the Int
and cs
the remainder of the list [(Char,Int)]
. 很显然,在列表不为空的情况下,其形式为
((ca,cb):cs)
其中ca
为Char
, cb
为Int
, cs
列表的其余部分[(Char,Int)]
。
In that case we can simply construct a string for that sequence ca:(show cb)
with show :: Show a => a -> String
we convert an integer to its String
counterpart. 在那种情况下,我们可以简单地为带有
show :: Show a => a -> String
ca:(show cb)
show :: Show a => a -> String
序列ca:(show cb)
构造一个字符串,我们将整数转换为其对应的String
。 Next we concatenate the flattening of remainder of the list to that string, so: 接下来,我们将列表的其余部分的拼合连接到该字符串,因此:
flatten ((ca,cb):cs) = ca:(show cb ++ flatten cs)
Or in full: 或全部:
flatten :: [(Char, Int)] -> String
flatten [] = []
flatten ((ca,cb):cs) = ca:(show cb ++ flatten cs)
First of all, we try to create a String
from a (Char, Int)
. 首先,我们尝试从
(Char, Int)
创建一个String
。 If we can do that we've almost done, since we can do that for all (Char, Int)
. 如果我们能够做到这一点,我们几乎就已经做到了,因为我们可以做到所有
(Char, Int)
。 So let's transform a single (Char, Int)
: 因此,让我们变换一个
(Char, Int)
:
flattenSingle :: (Char, Int) -> String
flattenSingle (c, i) = c : show i
Now, we need to do that for all entries: 现在,我们需要对所有条目执行此操作:
flattenAll :: [(Char, Int)] -> [String]
flattenAll xs = map flattenSingle xs
And last, but not least, we need to concat
the [String]
(which is a [[Char]]
) to a String
(which is a [Char]
): 而在去年,但并非最不重要,我们需要
concat
了[String]
(这是一个[[Char]]
)的String
(这是一个[Char]
):
flatten :: [(Char, Int)] -> String
flatten xs = concat (flattenAll xs)
And we're done. 我们完成了。 How did we do that?
我们是如何做到的? Well, we've started with a much easier problem, namely how to get a single
String
from a (Char, Int)
, and used that to get our result. 好吧,我们从一个更简单的问题开始,即如何从
(Char, Int)
获得单个String
,并以此来获得结果。
Here's everything in a single function: 这是单个函数中的所有内容:
flatten = concat . map flattenSingle
where
flattenSingle (c, i) = c : show i
Since concat . map f
自
concat . map f
以来concat . map f
concat . map f
is often used, there's a function for that, called concatMap
: concat . map f
是经常使用的,有一个函数叫做concatMap
:
flatten :: [(Char, Int)] -> String
flatten = concatMap flattenSingle
where
flattenSingle (c, i) = c : show i
Let's think about what goes into flatten
and what comes out of it. 让我们考虑一下
flatten
和flatten
的结果。 flatten
, takes a list of pairs of type: (Char, Int)
and produces a [Char]
; flatten
,获取类型对的列表: (Char, Int)
并产生[Char]
; it produces a list from an existing list. 它从现有列表中生成一个列表。 Does this ring a bell?
这会响吗?
flatten xs = [ c | (char, int) <- xs, c <-[char] ++ show int]
We can sequentially deconstruct each pair in the given list; 我们可以顺序地解构给定列表中的每一对。 for each pair, we turn each component into a string so we can concatenate them.
对于每一对,我们将每个组件转换为字符串,以便可以将它们连接起来。 Now we have a string for each pair, we just need to take each character out to produce the final string.
现在,每对都有一个字符串,我们只需要取出每个字符即可生成最终的字符串。
You might also use foldl
to make your intention very clear: 您还可以使用
foldl
来使意图非常清楚:
a=[('a',5),('b',4),('c',2)]
f b (x,y)=b++[x]++(show y)
result=foldl f "" a
Or you can make it a one-liner: 或者您可以将其设置为单线:
Solution 1: 解决方案1:
foldl (\b (x,y)->b++[x]++(show y)) "" a
Solution 2: 解决方案2:
concat $ map (\(x,y)->[x]++show y) a
Solution 3: (Being more efficient compared to solution 1) 解决方案3 :(与解决方案1相比效率更高)
foldr (\(x,y) b->b++[x]++(show y)) "" a
flatten = mconcat. map (\(c,i) -> [c] ++ show i)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.