Haskell 中的元音数据类型可能吗?
我编写了以下代码来从句子中删除元音:
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
只是想知道是否可以为元音创建数据类型?编译器不允许我在数据类型中使用字符。
I have written the following code to remove vowels from a sentence:
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
Just wondering if it is possible to create a data type for vowel? The compiler won't let me use characters in a data type.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不直接。问题在于字符是内置类型,不具备多态性。这与数字文字不同,数字文字被设计为通过
Num
类型类实现多态。也就是说,您可以采用两种基本方法:带有智能构造函数的新类型包装器,或全新类型。
newtype 包装器更易于使用:
由于
Vowel
构造函数未导出,因此新的Vowel
只能由vowel
函数创建,它只接受你想要的字符。您还可以创建一个像这样的新类型:
第二种方法非常重量级,因此使用起来更加尴尬。
这就是如何做到这一点。但我不太确定你是否愿意。通常的习惯用法是创建代表您的数据的类型,并且您特别不代表元音。一个常见的模式是这样的:
这里新类型区分未经净化和净化的输入。如果创建
CleanString
的唯一方法是通过cleanString
,那么您静态地知道每个CleanString
都已正确清理(前提是cleanString
是正确的)。就您而言,您似乎实际上需要一种辅音类型,而不是元音类型。Haskell 中的新类型非常轻量级*,但程序员必须编写和使用代码来进行包装和解包。在许多情况下,好处超过了额外的工作。但是,我真的想不出有任何应用程序知道您的
String
是无元音的,所以我可能只使用普通的String
。*newtypes 仅存在于编译时,因此理论上使用它们不会产生运行时性能成本。然而,它们的存在可能会改变生成的代码(例如禁止规则),因此有时会产生可测量的性能影响。
Not directly. The problem is that characters are a built-in type with no facility for polymorphism. This is different from numeric literals, which are designed to be polymorphic via the
Num
type class.That said, there are two basic approaches you can take: a newtype wrapper with a smart constructor, or a totally new type.
The newtype wrapper is easier to use:
Since the
Vowel
constructor isn't exported, newVowel
s can only be created by thevowel
function, which only admits the characters you want.You could also make a new type like this:
This second way is pretty heavyweight, and therefore is much more awkward to use.
So that's how to do it. I'm not quite certain that you want to though. The usual idiom is to make types that represent your data, and you specifically don't represent vowels. A common pattern would be something like this:
Here the newtype differentiates between unsanitized and sanitized input. If the only way to make a
CleanString
is bycleanString
, then you know statically that everyCleanString
is properly sanitized (provided thatcleanString
is correct). In your case, it seems you actually need a type for consonants, not vowels.Newtypes in Haskell are very lightweight*, but the programmer does have to write and use code to do the wrapping and unwrapping. In many instances the benefits outweigh the extra work. However, I really can't think of any application where it's important to know that your
String
is vowel-free, so I'd probably just work with a plainString
.*newtypes only exist at compile-time, so in theory there's no runtime performance cost to using them. However, their existence can change the produced code (e.g. inhibiting RULEs), so sometimes there is a measurable performance impact.
您可以使用 幻像类型 来标记具有额外信息的字符,以便在运行期间使类型系统保证编译时您的字符串仅包含元音或非元音等。
这是一个玩具示例:
这种方法的好处是您仍然可以编写适用于所有 TaggedChar 的函数,而不管标签如何。例如:
You could use phantom types to tag characters with extra information, in order to make the type system guarantee during compile time that your strings only contain, for example, vowels or non-vowels.
Here's a toy example:
The benefit of this approach is that you can still also write functions that work on all TaggedChars regardless of the tag. For example: