首次尝试Haskell:将小写字母转换为大写字母

时间:2013-12-09 19:27:39

标签: haskell functional-programming

我最近开始学习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
   ""
  1. 我不喜欢我通过大写和小写的方式 字母,我不能只声明一个全局变量吗?
  2. 你的做法是什么方法填补其他分支?
  3. 您对改善这一点的建议是什么?

2 个答案:

答案 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满足的OrdChar类型类。 fromEnum cc转换为ASCII码,toEnum将ASCII码转换为等效字符。我提供给map的函数只是检查字符是否为小写,如果是,则减去32('A'和'a'之间的差值),否则单独留下。

当然,你总是可以写:

import Data.Char
uppercase :: String -> String
uppercase = map toUpper

希望这有帮助!

答案 1 :(得分:4)

在我们的环境中,我总是向人们推荐的是:

  1. 将问题分解为更小的部分,并为每个部分编写单独的函数。
  2. 尽可能使用库函数来解决较小的子问题。
  3. 完成后的练习,弄清楚如何自己编写你使用的库函数。
  4. 在这种情况下,我们可以按如下方式应用这些要点。首先,由于Haskell中的String[Char]Char列表)的同义词,我们可以将您的问题分解为这两部分:

    • 将角色转换为大写字母。
    • 通过分别对每个成员应用一个函数来转换列表。

    第二点:正如Alex的答案所指出的那样,Data.Char标准库模块附带了一个执行第一个任务的函数toUpper,而Prelude库附带了map执行第二次。因此,使用这两个一起解决您的问题(这正是Alex之前写的代码):

    import Data.Char
    uppercase :: String -> String
    uppercase = map toUpper
    

    但我会说这是最好的解决方案(最短和最清晰),作为初学者,这是你应该尝试的第一个答案

    应用我的第三点:在你提出标准解决方案之后,尝试编写你自己的库函数版本是非常有教育意义的。关键是你通过这种方式学到三件事:

    1. 如何将问题分解为更容易,更小的部分,最好是可重复使用的部分;
    2. 该语言标准库的内容;
    3. 如何编写库提供的简单“基础”功能。
    4. 因此,在这种情况下,您可以尝试编写自己的toUppermap版本。我将为map提供一个框架:

      map :: (a -> b) -> [a] -> [b]
      map f [] = ???
      map f (x:xs) = ???