检查字符串在 Haskell 中是不区分大小写的回文
Checking String is a Palindrome Case Insensitive in Haskell
我正在尝试编写一个函数来检查 Haskell 中的字符串是否为回文(不区分大小写)。为确保大写字符不会导致问题,我首先使用 toLower
(https://hackage.haskell.org/package/text-2.0/docs/Data-Text.html#v:toLower) 将字符串转换为小写。然后我检查它是否等于同一事物的反转版本。这是我的代码:
{-# LANGUAGE OverloadedStrings #-}
import Data.Text (toLower)
isPalindrome :: String -> Bool
isPalindrome xs = toLower xs == toLower $ reverse xs
我意识到 toLower
使用文本而不是字符串,我们需要使用 {-# LANGUAGE OverloadedStrings #-}
将字符串重载为文本。但这不编译。
我也在 GHCI 中复制了这个。我首先使用 :set -XOverloadedStrings
来确保重载字符串。然后我运行这个:
Prelude Data.Text> toLower $ reverse "sdssSDSS"
<interactive>:92:11: error:
• Couldn't match expected type ‘Data.Text.Internal.Text’
with actual type ‘[Char]’
• In the second argument of ‘($)’, namely ‘reverse "sdssSDSS"’
In the expression: toLower $ reverse "sdssSDSS"
In an equation for ‘it’: it = toLower $ reverse "sdssSDSS"
我不明白为什么这不起作用。如果我先 运行 reverse "sdssSDSS"
并将结果复制粘贴到 toLower
中,它可以正常工作。
and we need to use {-# LANGUAGE OverloadedStrings #-}
to overload String
to Text
没有。该扩展名应该被称为 OverloadedStringLiterals
。它只会改变 文字 的行为,例如 "hello"
或 "sdssSDSS"
,但不会在 String
和 Text
之间转换。通常,自动转换 永远不会 发生在 Haskell 中,所发生的只是您可以拥有多态值,例如具有该扩展名的数字文字或字符串文字。
在现代 Haskell 中,最好的选择可能就是将其全部写在 Text
中并且根本不引入 String
:
import qualified Data.Text as Txt
isPalindrome :: Txt.Text -> Bool
isPalindrome xs = Txt.toLower xs == Txt.toLower (Txt.reverse xs)
(请注意,您不能在此处使用 $
,因为它的优先级低于 ==
)。
但是你根本不需要使用Text
,还有toLower
的single-character版本:
import Data.Char (toLower)
isPalindrome :: String -> Bool
isPalindrome xs = map toLower xs == map toLower (reverse xs)
顺便说一句,在这两种情况下,都可以只使用一次 toLower
:
isPalindrome :: String -> Bool
isPalindrome xs = xsLC == reverse xsLC
where xsLC = map toLower xs
leftaroundabout 已经向您解释了如何解决您的问题,但我还有一点补充。如果你想使用文本类型的常规 Char -> Char 函数,你可以使用 Lens 和 unpacked ISO 轻松完成(这很方便但很慢 :))。
{-# LANGUAGE OverloadedStrings #-}
import Control.Lens
import qualified Data.Text as T
useFun1 :: (String -> String) -> T.Text -> T.Text
useFun1 = over unpacked
useFun2 :: (Char -> Char) -> T.Text -> T.Text
useFun2 = over (unpacked . traversed)
我正在尝试编写一个函数来检查 Haskell 中的字符串是否为回文(不区分大小写)。为确保大写字符不会导致问题,我首先使用 toLower
(https://hackage.haskell.org/package/text-2.0/docs/Data-Text.html#v:toLower) 将字符串转换为小写。然后我检查它是否等于同一事物的反转版本。这是我的代码:
{-# LANGUAGE OverloadedStrings #-}
import Data.Text (toLower)
isPalindrome :: String -> Bool
isPalindrome xs = toLower xs == toLower $ reverse xs
我意识到 toLower
使用文本而不是字符串,我们需要使用 {-# LANGUAGE OverloadedStrings #-}
将字符串重载为文本。但这不编译。
我也在 GHCI 中复制了这个。我首先使用 :set -XOverloadedStrings
来确保重载字符串。然后我运行这个:
Prelude Data.Text> toLower $ reverse "sdssSDSS"
<interactive>:92:11: error:
• Couldn't match expected type ‘Data.Text.Internal.Text’
with actual type ‘[Char]’
• In the second argument of ‘($)’, namely ‘reverse "sdssSDSS"’
In the expression: toLower $ reverse "sdssSDSS"
In an equation for ‘it’: it = toLower $ reverse "sdssSDSS"
我不明白为什么这不起作用。如果我先 运行 reverse "sdssSDSS"
并将结果复制粘贴到 toLower
中,它可以正常工作。
and we need to use
{-# LANGUAGE OverloadedStrings #-}
to overloadString
toText
没有。该扩展名应该被称为 OverloadedStringLiterals
。它只会改变 文字 的行为,例如 "hello"
或 "sdssSDSS"
,但不会在 String
和 Text
之间转换。通常,自动转换 永远不会 发生在 Haskell 中,所发生的只是您可以拥有多态值,例如具有该扩展名的数字文字或字符串文字。
在现代 Haskell 中,最好的选择可能就是将其全部写在 Text
中并且根本不引入 String
:
import qualified Data.Text as Txt
isPalindrome :: Txt.Text -> Bool
isPalindrome xs = Txt.toLower xs == Txt.toLower (Txt.reverse xs)
(请注意,您不能在此处使用 $
,因为它的优先级低于 ==
)。
但是你根本不需要使用Text
,还有toLower
的single-character版本:
import Data.Char (toLower)
isPalindrome :: String -> Bool
isPalindrome xs = map toLower xs == map toLower (reverse xs)
顺便说一句,在这两种情况下,都可以只使用一次 toLower
:
isPalindrome :: String -> Bool
isPalindrome xs = xsLC == reverse xsLC
where xsLC = map toLower xs
leftaroundabout 已经向您解释了如何解决您的问题,但我还有一点补充。如果你想使用文本类型的常规 Char -> Char 函数,你可以使用 Lens 和 unpacked ISO 轻松完成(这很方便但很慢 :))。
{-# LANGUAGE OverloadedStrings #-}
import Control.Lens
import qualified Data.Text as T
useFun1 :: (String -> String) -> T.Text -> T.Text
useFun1 = over unpacked
useFun2 :: (Char -> Char) -> T.Text -> T.Text
useFun2 = over (unpacked . traversed)