我最近开始学习Haskell,我已经尝试创建一个函数,以便将小写单词转换为大写单词,它可以工作,但我不知道它有多好,我有一些问题。 代码:
lowerToUpperImpl element list litereMari litereMici =
do
if not (null list) then
if (head list) == element then
['A'..'Z'] !! (length ['A'..'Z'] - length (tail list ) -1)
else
lowerToUpperImpl element (tail list) litereMari litereMici
else
'0' --never to be reached
lowerToUpper element = lowerToUpperImpl element ['a'..'z'] ['A'..'Z'] ['a'..'z']
lowerToUpperWordImpl word =
do
if not (null word) then
lowerToUpper (head (word)):(lowerToUpperWordImpl (tail word))
else
""
您对改善这一点的建议是什么?
答案 0 :(得分:8)
首先,if / else通常被视为函数式编程语言中的拐杖,正是因为它们不是真的应该用作分支操作,而是用作函数。还要记住,列表在Haskell中不知道自己的长度,因此计算它是O(n)
步。这对于无限列表来说尤其糟糕。
我会更喜欢这样写(如果我没有导入任何库):
uppercase :: String -> String
uppercase = map (\c -> if c >= 'a' && c <= 'z' then toEnum (fromEnum c - 32) else c)
让我解释一下。此代码使用Enum
满足的Ord
和Char
类型类。 fromEnum c
将c
转换为ASCII码,toEnum
将ASCII码转换为等效字符。我提供给map
的函数只是检查字符是否为小写,如果是,则减去32('A'和'a'之间的差值),否则单独留下。
当然,你总是可以写:
import Data.Char
uppercase :: String -> String
uppercase = map toUpper
希望这有帮助!
答案 1 :(得分:4)
在我们的环境中,我总是向人们推荐的是:
在这种情况下,我们可以按如下方式应用这些要点。首先,由于Haskell中的String
是[Char]
(Char
列表)的同义词,我们可以将您的问题分解为这两部分:
第二点:正如Alex的答案所指出的那样,Data.Char
标准库模块附带了一个执行第一个任务的函数toUpper
,而Prelude
库附带了map
执行第二次。因此,使用这两个一起解决您的问题(这正是Alex之前写的代码):
import Data.Char
uppercase :: String -> String
uppercase = map toUpper
但我会说这是最好的解决方案(最短和最清晰),作为初学者,这是你应该尝试的第一个答案。
应用我的第三点:在你提出标准解决方案之后,尝试编写你自己的库函数版本是非常有教育意义的。关键是你通过这种方式学到三件事:
因此,在这种情况下,您可以尝试编写自己的toUpper
和map
版本。我将为map
提供一个框架:
map :: (a -> b) -> [a] -> [b]
map f [] = ???
map f (x:xs) = ???