我需要通过两个int值的给定输入在水平和垂直方向上拉伸haskell中的字符串。我有正确的代码,只是不知道如何正确实现它:
expansion :: Int -> Int -> String -> String
expansion extendTo e n m a = setSize e (max n $ nrows a) (max m $ ncols a) a
它在书中指出,它将输入图像按第一和第二个参数提供的整数进行缩放。例如,如果exPic是图片:
#.#
..#
那么扩展exPic 2 2的结果应该是:
##..##
##..##
....##
....##
我使用的书没有提供任何解决方案,否则我不会要求!!
答案 0 :(得分:4)
这个答案是literate Haskell。您可以使用.lhs
扩展名对其进行保存,然后将其加载到GHCi中。
要拉伸元素列表,我们需要复制每个元素,然后将生成的列表列表拼接成单个列表。为此,我们将replicate
函数映射到元素上,然后使用concatMap
将结果列表重新拼接在一起:
> stretch :: Int -> [a] -> [a]
> stretch n = concatMap (replicate n)
注意:这也可以将 pointfree 定义为
stretch = concatMap . replicate
现在我们可以通过拉伸行并通过映射行来拉伸网格(列表列表)来拉伸其中的元素:
> expand :: Int -> Int -> [[a]] -> [[a]]
> expand n m = stretch n . map (stretch m)
我们可以使用相同的结果(expand n m = map (stretch m) . stretch n
)来反转订单吗?为什么或为什么不呢?
现在唯一让它与你的例子一起工作的缺失就是在包含换行符的字符串和在换行符上拆分的字符串列表之间来回转换。 lines
和unlines
将为我们执行此操作。 (如果您的实际应用涉及网格而不是字符串,则您不需要这样做。)
> expansion :: Int -> Int -> String -> String
> expansion n m = unlines . expand n m . lines
为什么我们在使用String
之前使用[a]
?
现在测试一下:
λ> putStrLn $ expansion 2 2 "#.#\n..#"
##..##
##..##
....##
....##