Haskell 如何使用控制镜头将字符串大写?
我正在玩Haskell 如何使用控制镜头将字符串大写?,haskell,haskell-lens,Haskell,Haskell Lens,我正在玩lens软件包,我试图只用lens将字符串大写。 基本上,我想对每个单词的第一个元素调用toUpper。这看起来很容易,但我根本不知道怎么做。我需要一个可遍历的吗?如何按空格等分割 capitalize xs = xs & words <&> _head %~ toUpper & unwords 这看起来是家喻户晓的\u head%~f将在列表的第一个元素上应用f。最后,这(几乎*)相当于 capitalize xs = unwords $ fmap
lens
软件包,我试图只用lens将字符串大写。
基本上,我想对每个单词的第一个元素调用toUpper
。这看起来很容易,但我根本不知道怎么做。我需要一个可遍历的吗?如何按空格等分割
capitalize xs = xs & words <&> _head %~ toUpper & unwords
这看起来是家喻户晓的\u head%~f
将在列表的第一个元素上应用f
。最后,这(几乎*)相当于
capitalize xs = unwords $ fmap (\(x:xs) -> toUpper x : xs) $ words $ xs
你可能很熟悉
*
\u head
还负责空列表大小写调用单词
然后取消单词
实际上不是同构,因为它会将重复的空格转换为单个空格,但让我们假装:
words :: Iso' String [String]
words = iso Prelude.words Prelude.unwords
现在我们可以通过构建一个聚焦于每个单词的第一个字母的透镜,并在和上应用touper来大写单词
capitalize :: String -> String
capitalize = over (words . traverse . _head) toUpper
不折叠重复空间的解决方案:
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)
如果你愿意考虑<代码>(单词,unWord)< /代码>一个同构,那么你可以通过一个对<>代码>( > .j.abrHAMSON的单次调用来完成这一切:谢谢你的额外回答。这实际上是我第一次使用镜头。使用Iso
的技巧非常棒。然而,我应该后退几步,阅读更多关于Traversable的内容,我完全忘记了traverse
,花了太多时间寻找一个操作符(我最终得到了over\uWords$fmap(\u head%~touper)
)我很高兴把单词和unWord看作同构,因为它只是一个穿越同构的例子。这就是我要找的。我正在ghci中尝试让w=isowords unwords::iso'String[String]
,我得到以下错误:没有(Profunctor p0)的实例。
。有什么想法吗?嗯。现在我必须实际安装lens
。我将在大约20分钟后回复。@mb14将类型签名放在自己的行上。如果您首先运行:set+m
,您将在GHCi中获得多行输入。这个问题是由于GHC的类型推断是如何处理独立类型签名的。inline@mb14或者,运行:set-XNoMonomorphismRestriction
,让GHCi按照您期望的方式解释它。
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)