我很难将Haskell和函数式编程放在一起。我想要做的是操纵一个字符串,以便每次根据给定的数字打印/返回特定字符。例如:
printing "testing" 2 = "etn"
printing "testing" 3 = "sn"
我在线阅读了很多内容,根据我的理解,我可以通过过滤和循环来实现这一目标,但是我无法获得/理解这种语言的语法来获得一个有效的程序。
我将尝试描述我的思维过程,以便您可以关注。此函数适合通过重复的函数应用程序(此处删除一些元素)从输入种子(此处为字符串)创建输出列表(此处为字符串)的模式。因此,我选择了Data.List.unfoldr
的实现。
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
好吧,我需要将种子b
变成(Maybe
)输出a
和其余的字符串。我将这个子功能称为f
并将其传递给unfoldr
。
printing s n = unfoldr f s
where f b = case drop n b of
[] -> Nothing
(x:xs) -> Just (x,xs)
事实证明,试图将头部从列表前面移开并返回Maybe
也是一种常见的模式。这是Data.List.uncons
,所以
printing s n = unfoldr (uncons . drop n) s
很顺利!所以我测试出来了,输出错了!实际上你的指定输出例如。对于n=2
选择每个第二个字符,即。滴(n-1)
字符。
printing s n = unfoldr (uncons . drop (n-1)) s
我再次测试它,它匹配所需的输出。唷!
为了向Haskell语言演示一些可接受的答案的替代解决方案。
使用列表理解:
printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]
使用递归:
printing' :: Int -> String -> String
printing' n ls
| null ls' = []
| otherwise = x : printing' n xs
where
ls' = drop (n - 1) ls
(x : xs) = ls'
在这两种情况下,我都翻转了参数,因此更容易进行部分应用:例如,printing 5
是一个新函数,当应用于字符串时将给出每个第5个字符。
注意稍作修改,它们适用于任何列表
takeEvery :: Int -> [a] -> [a]