【问题标题】:How to convert a String to lowercase using lambda expressions如何使用 lambda 表达式将字符串转换为小写
【发布时间】:2017-03-01 19:58:18
【问题描述】:

我想知道如何使用ToLower 函数(Char -> Char) 将字符串转换为小写。

这是我目前的代码:

let newlist = (\(h:t) -> c (h) ++ newlist (\c -> toLower c)

如果不使用递归,我看不到该怎么做,我不知道如何在 lambda 表达式中使用它

【问题讨论】:

  • let lowercase = map toLower。然后,将其称为lowercase "Hello"

标签: haskell lambda lowercase


【解决方案1】:

考虑到您可以 eta-reduce 不显式命名您的函数接受的变量,因此不使用 lambda 表达式会更容易。例如,您可以使用列表推导:

import Data.Char

lowerString str = [ toLower loweredString | loweredString <- str]

你会这样称呼:

ghci> lowerString "Hello"
hello

或者,您可以使用map

lowerString = map toLower

如果你坚持使用 lambda 表达式,它看起来像这样:

import Data.Char

lowerString = \x -> map toLower x

这又不是那么好。

【讨论】:

    【解决方案2】:

    使用 lambda 表达式,您仍然需要递归检查字符串的每个字符,或者您可以使用 ma​​p,它仍然是一个应用函数 (a -> b) 到列表中的每个元素,例如:

      newList [] = []
      newList xs = (\(y:ys) -> if x `elem` ['A'..'Z'] then toLower y : newList ys else y : newList ys) xs
    

    由于第一段中解释的原因,使用 ma​​p 实际上要简单得多,请检查 mnoronha 的答案,因为他已经给了您答案,但那是如果您正在考虑将 map 与 toLower 结合使用.

    这是一个没有 lambda 表达式的示例,它要求您从 Data.Char 导入 2 个函数,递归检查字符串的其余部分并将每个字符替换为其小写版本。

    newList :: String -> String
    newList [] = []
    newList (x:xs) = if x `elem` ['A'..'Z'] 
                   then chr (ord x + 32) : newList xs 
                   else x : newList xs  
    

    或带警卫

    newList :: String -> String
    newList [] = []
    newList (x:xs)
        | x `elem` ['A'..'Z'] = chr (ord x + 32) : newList xs 
        | otherwise = x : newList xs 
    

    【讨论】:

    • 你测试过你的代码吗?它看起来一旦到达字符串的末尾就会失败,因为您从未指定如何处理空尾 []
    • 现在应该可以了,我在处理列表时总是忘记这一点,谢谢
    • s==[] 将永远为假,因为s = x:xs 所以它不是空的。
    【解决方案3】:

    这可能比它的价值更麻烦,但您可以使用 fix 函数递归调用 lambda 函数。

    fix :: (a -> a) -> a
    fix f = let x = f x in x
    

    以下代码使用与本页相同的方法:https://www.vex.net/~trebla/haskell/fix.xhtml 从非 lambda 版本转换为 lambda 版本,以(最终)使用 fix 递归调用 lambda 函数而不引入新变量

    import Data.Char (toLower)
    import Control.Monad.Fix (fix)
    
    main :: IO ()
    main = do 
        -- calling non lambda version
        let newlist1 s = if null s then [] else toLower (head s) : newlist1 (tail s)
        print $ newlist1 "Hello"
    
        -- calling lambda version
        let newlist2 = \s -> if null s then [] else toLower (head s) : newlist2 (tail s)
        print $ newlist2 "Hello"
    
        -- defining lambda version locally
        -- ( at this point the scope of newlist3 is local to the let statement )
        print $ (let newlist3 = \s -> if null s then [] else toLower (head s) : newlist3 (tail s) in newlist3 ) "Hello"
    
        -- making function an argument to be called recursively
        print $ (let newlist3 = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s)) newlist3 in newlist3 ) "Hello"
    
        -- isolating function to be "fixed".
        let f = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s))
        print $ (let newlist3 =  f newlist3 in newlist3 ) "Hello"
    
        -- using fix = let x = f x in x
        print $ (fix f) "Hello"
    
        -- f2 is slightly simpler version of f
        let f2 = (\v s -> if null s then [] else toLower (head s) : v (tail s))
        print $ (fix f2) "Hello"
    
        -- inlining f2 to get recursive call to lambda 
        print $ (fix (\v s -> if null s then [] else toLower (head s) : v (tail s))) "Hello"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2012-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多