在 Haskell 中反转订单

Reversing an Order in Haskell

我正在努力自学 Haskell,我还很新,所以我想知道是否有人可以帮助我。我正在尝试编写一个函数来反转名称的顺序,这样如果我键入

ghci> fullName "harry" "potter" 

我应该得到,

"potter, harry"

我尝试过的:

我知道要打印出前两个字符,我需要做

initials :: String -> String -> String
initials firstname lastname = [l] ++ [b] ++ ", " ++ [f] ++ [a]
        where (f:a:_) = firstname
              (l:b:_) = lastname

这将得到:

ghci> initials "harry" "potter"
"po, ha"

它可以工作,但问题是当您不知道名称中有多少个字符时它需要工作。无论多长时间,我都应该能够输入任何随机名称,并且它应该能够颠倒顺序。我觉得这是非常明显的事情,但我不明白。

String[Char] 的类型别名,因此您可以将 ++

一起使用
fullname :: String -> String -> String
fullname first last = last ++ ", " ++ first

首先,作为提示,您可以将您所拥有的更地道地写成

initials (f:a:_) (l:b:_) = [l, b] ++ ", " ++ [f, a]

但这就是所谓的偏函数(不要与偏函数应用混淆)。在这里我的意思是一个函数可以是部分的或全部的。如果一个函数是总函数,那么它是为它的输入类型的所有可能值定义的。 initials 没有为输入 initials "" "" 定义,例如,所以你会得到一个模式匹配错误,表明它不是总的。更数学地说,这意味着对于 f :: A -> B,对于 A 中的所有 aB 中有一个 b 使得 f a = b.

有两种(常见的)方法可以实现这样的功能。您可以使用更多模式匹配,例如

initials [] [] = ", "
initials [a] [] = ", " ++ [a]
initials [] [b] = [b] ++ ", "
initials (f:a:_) (l:b:_) = [l, b] ++ ", " ++ [f, a]

或者您可以使用内置函数 take:

initials firstname lastname = take 2 lastname ++ ", " ++ take 2 firstname

第二个更简洁,避免了匹配每个模式的担忧,但有时模式匹配绝对是可行的方法。

对于任意长度的名称,由于 String[Char] 相同,您可以像使用 ++ ", " ++ 一样使用 ++:

fullname firstname lastname = lastname ++ ", " ++ firstname