我正在使用lens
包,我正在尝试仅使用镜头来大写字符串。
基本上我想在每个单词的每个第一个元素上调用toUpper
。这似乎很容易,但我根本无法弄清楚如何做到这一点。我需要一个可穿越的吗?我如何按空格等分割......
答案 0 :(得分:4)
调用words
然后调用unwords
并不是真正的同构,因为它会将重复的空格转换为单个空格,但让我们假装:
words :: Iso' String [String]
words = iso Prelude.words Prelude.unwords
现在我们可以通过构建一个镜头来大写单词,该镜头专注于每个单词的第一个字母并应用over
和toUpper
capitalize :: String -> String
capitalize = over (words . traverse . _head) toUpper
答案 1 :(得分:3)
capitalize xs = xs & words <&> _head %~ toUpper & unwords
好的,这是解决方案,但如何到达那里?让我们删除一些镜头部件。将(<&>)
与fmap
和(&)
与($)
交换:
capitalize xs = unwords $ fmap (_head %~ toUpper) $ words $ xs
这看起来很熟悉。 _head %~ f
会在列表的第一个元素上应用f
。最后,这是(几乎 * )等同于
capitalize xs = unwords $ fmap (\(x:xs) -> toUpper x : xs) $ words $ xs
你可能熟悉的。
* _head
也会处理空列表案例
答案 2 :(得分:3)
不会崩溃重复空格的解决方案:
import Control.Lens
import Data.List.Split
import Data.List.Split.Lens
import Data.Char
capitalize :: String -> String
capitalize = view $ splitting (whenElt isSpace) traversed.to (over _head toUpper)