- 论坛徽章:
- 2
|
回复 52# Monox
Text.XML.Light简单完全是轻信了那个帖子里的言论。 不过也没有时间一个一个去试就是了。
用过之后并不满意, 也就是前面提到的它自定义类型的同时需要新的操作数据的方法, 所以才会继续提到type class。
而你说Arrow是因为HXT用它吧?
List是有Monad instance的, 不过不是用来做查找的而是list comprehension。
不能确定会不会有人会为Map实现一个, 但base里好像没有。
Prelude.lookup和Data.Map.lookup在base里好像也没有相应的type class。 Data.Foldable 可以用, 但对查找来说太低效了。
非常极端的是这货: ClassyPrelude 。。。
虽然作者的初衷并不是这样。。。
不过作者原本意图那样使用type class也能缓解数据类型一改,一大堆代码都要修改的问题。。。
和type class相比interface弱爆了。。。
一方面interface是操作与对象耦合,于是它就没法:
- minBound :: Bounded a => a
- maxBound :: Bounded a => a
- mempty :: Monoid a => a
复制代码 等等。 要实现:
- (==) :: Eq a => a -> a -> Bool
- (+) :: Num a => a -> a -> a
复制代码 等等也会比较麻烦。
像
- elem :: Eq a => a -> [a] -> Bool
复制代码 这样的操作,那个实现多态的东西会重复出现在集合的每一个元素上。
Haskell里没有这样的耦合,并且可以需要的时候再将操作与对象耦合在一起。
另一方面,interface将定义数据类型与实现interface耦合。
定义数据类型时怎么可能想得全它可以实现哪些interface?
比如前面提到的Data.Map, 不管是为它实现CanLookup还是IsMap都是在定义Data.Map之后而不是同时发生的事情。
不管实现与否,不管实现多少个,Data.Map总在那里,总是那个Data.Map。
而如果必须同时定义数据类型并实现相应的interface, 就会出现这样的情况。。。
A定义了X类型并实现了I接口。
B发现X其实还可以实现J接口。 于是他就面临选择:
1. 等作者改。 不一定能得到
2. 自己改。 要能获取源代码。 并且还得考虑接下来和upstream的合并问题。 有可能并不是upstream懒,而是他因为各种原因不愿意让X实现J。 那之后就只能自己考虑将upstream的更新合并到自己这里。。
3. 定Y作为X的wrapper,并实现I,J接口。。。
|
|