Ric*_*sse 7 haskell types functional-programming pattern-matching
我写了以下代码来删除句子中的元音:
main = print $ unixname "The House"
vowel x = elem x "aeiouAEIOU"
unixname :: [Char] -> [Char]
unixname [] = []
unixname (x:xs) | vowel x = unixname xs
| otherwise = x : unixname xs
Run Code Online (Sandbox Code Playgroud)
只是想知道是否可以为元音创建数据类型?编译器不允许我在数据类型中使用字符.
Joh*_*n L 15
不是直接的.问题是字符是内置类型,没有多态性.这与数字文字不同,数字文字通过Num类型类设计为多态的.
也就是说,您可以采用两种基本方法:带有智能构造函数的newtype包装器或全新类型.
newtype包装器更易于使用:
module Vowel (Vowel, vowel, fromVowel) where
newtype Vowel = Vowel Char
vowel :: Char -> Maybe (Vowel)
vowel x | x `elem` "aeiouAEIOU" = Just (Vowel x)
| otherwise = Nothing
fromVowel :: Vowel -> Char
fromVowel (Vowel x) = x
Run Code Online (Sandbox Code Playgroud)
由于Vowel未导出构造函数,因此只能Vowel由vowel函数创建new s,该函数只允许您想要的字符.
您也可以创建一个这样的新类型:
data Vowel = A | E | I | O | U | Aa | Ee | Ii | Oo | Uu
fromChar :: Char -> Maybe Vowel
fromChar 'a' = Just Aa
fromChar 'A' = Just A
-- etc.
toChar :: Vowel -> Char
toChar Aa = 'a'
toChar A = 'A'
Run Code Online (Sandbox Code Playgroud)
第二种方式非常重量级,因此使用起来更加笨拙.
这就是如何做到的.我不太确定你想要的.通常的成语是使代表你的数据类型,并且你特别不代表元音.一个常见的模式是这样的:
newtype CleanString = Cleaned { raw :: String }
-- user input needs to be sanitized
cleanString :: String -> CleanString
Run Code Online (Sandbox Code Playgroud)
这里newtype区分未经过消毒和已消毒的输入.如果制作a的唯一方法CleanString是cleanString,那么你就会静静CleanString地知道每一个都经过适当的消毒(前提是这cleanString是正确的).在你的情况下,你似乎确实需要一个辅音类型,而不是元音.
Haskell中的Newtypes非常轻量级*,但程序员必须编写并使用代码来进行包装和解包.在许多情况下,好处超过了额外的工作.但是,我真的想不出任何重要的事情,知道你String的元音是免费的,所以我可能只是简单地工作String.
*newtypes仅在编译时存在,因此理论上使用它们没有运行时性能成本.但是,它们的存在可以改变生成的代码(例如,禁止RULE),因此有时会产生可测量的性能影响.
您可以使用幻像类型来标记带有额外信息的字符,以便在编译期间使类型系统保证您的字符串仅包含元音或非元音.
这是一个玩具示例:
{-# LANGUAGE EmptyDataDecls #-}
import Data.Maybe
newtype TaggedChar a = TaggedChar { fromTaggedChar :: Char }
data Vowel
data NonVowel
isVowel x = x `elem` "aeiouyAEIOUY"
toVowel :: Char -> Maybe (TaggedChar Vowel)
toVowel x
| isVowel x = Just $ TaggedChar x
| otherwise = Nothing
toNonVowel :: Char -> Maybe (TaggedChar NonVowel)
toNonVowel x
| isVowel x = Nothing
| otherwise = Just $ TaggedChar x
unixname :: [Char] -> [TaggedChar NonVowel]
unixname = mapMaybe toNonVowelRun Code Online (Sandbox Code Playgroud)
这种方法的好处是你仍然可以编写适用于所有TaggedChars的函数,无论标记如何.例如:
toString :: [TaggedChar a] -> String
toString = map fromTaggedCharRun Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1768 次 |
| 最近记录: |