我有两个字符串作为 Haskell 函数的参数。
s1
小于s2
ifs1
小于s2
或 如果它们具有相同的长度并且按s1
字典顺序小于s2
。
如何在 Haskell 中实现这一点?
我会使用以下内容:
smaller :: String -> String -> Bool
smaller s1 s2 | len1 /= len2 = (len1 < len2)
| otherwise = (s1 < s2)
where (len1, len2) = (length s1, length s2)
这是一个运行示例,在 Hugs 中:
主>较小的“b”“aa” 真的 主>较小的“aa”“b” 错误的 主>较小的“这个”“那个” 错误的 Main> 较小的“那个”“这个” 真的
一次性解决方案:
lengthcompare :: Ord a => [a] -> [a] -> Ordering
lengthcompare = lc EQ
where
lc lx [] [] = lx
lc _ [] _ = LT
lc _ _ [] = GT
lc EQ (v:vs) (w:ws) = lc (compare v w) vs ws
lc lx (_:vs) (_:ws) = lc lx vs ws
smaller :: Ord a => [a] -> [a] -> Bool
smaller s1 s2 = lengthcompare s1 s2 == LT
试试这个:
compare s1 s2
(这将返回 LT、EQ 或 GT)。
mappend
上面 Tom Lokhorst 版本的较短版本:
import Data.Monoid (mappend)
import Data.Ord (comparing)
compareStrings :: String -> String -> Ordering
compareStrings = comparing length `mappend` comparing id
另一种方式,利用元组的顺序:
import Data.Ord (comparing)
import Control.Arrow ((&&&))
compareStrings :: String -> String -> Ordering
compareStrings = comparing (length &&& id)
String
是的一个实例,Ord
因此您可以使用所有这些方法按字典顺序比较字符串。正如安德鲁所说,这本质上compare
是比较运算符(<)
等。
smaller :: Ord a => a -> a -> Bool
smaller a b = a < b
这适用于所有类型的实现Ord
(实际上只是 的粗略包装(<)
),包括String
.
正常的字符串比较仅适用于字典顺序,而不适用于字符串的长度。
因此,您必须编写自己的函数来检查长度:
smaller :: String -> String -> Bool
smaller s1 s2 | length s1 < length s2 = True
| length s1 > length s2 = False
| otherwise = s1 < s2
或者更笼统一些:
compareStrings :: String -> String -> Ordering
compareStrings s1 s2 | length s1 < length s2 = LT
| length s1 > length s2 = GT
| otherwise = compare s1 s2
例子:
ghci> compare "ab" "z"
LT
ghci> compareStrings "ab" "z"
GT
上周我们在大学里玩弄 Monoids,我们想出了这个可爱的替代Ord
实例:
instance Ord a => Ord [a] where
compare = comparing length
`mappend` comparing head `mappend` comparing tail
但是如果你不太明白这一点,我建议你坚持第一个定义;-)