我是一名C#开发人员。从面向对象的角度出发,我首先从接口、类和类型层次结构的角度进行思考。由于Haskell缺乏面向对象,有时我发现自己被卡住了,我想不出一种方法来模拟Haskell的某些问题。
如何在Haskell中对涉及类层次结构的实际情况进行建模,如下所示:http://www.braindelay.com/danielbray/endangered-object-oriented-programming/isHierarchy-4.gif
发布于 2010-06-27 00:39:19
让我们假设以下操作:人类可以说话,狗可以叫,一个物种的所有成员都可以与同一物种的成员交配,如果他们是异性的。我在haskell中是这样定义的:
data Gender = Male | Female deriving Eq
class Species s where
gender :: s -> Gender
-- Returns true if s1 and s2 can conceive offspring
matable :: Species a => a -> a -> Bool
matable s1 s2 = gender s1 /= gender s2
data Human = Man | Woman
data Canine = Dog | Bitch
instance Species Human where
gender Man = Male
gender Woman = Female
instance Species Canine where
gender Dog = Male
gender Bitch = Female
bark Dog = "woof"
bark Bitch = "wow"
speak Man s = "The man says " ++ s
speak Woman s = "The woman says " ++ s现在,操作matable的类型为Species s => s -> s -> Bool,bark的类型为Canine -> String,speak的类型为Human -> String -> String。
我不知道这是否有帮助,但考虑到这个问题相当抽象的性质,这是我能想到的最好的办法。
编辑:回应Daniel的评论:
一个简单的集合层次结构可能如下所示(忽略已经存在的类,如Foldable和Functor):
class Foldable f where
fold :: (a -> b -> a) -> a -> f b -> a
class Foldable m => Collection m where
cmap :: (a -> b) -> m a -> m b
cfilter :: (a -> Bool) -> m a -> m a
class Indexable i where
atIndex :: i a -> Int -> a
instance Foldable [] where
fold = foldl
instance Collection [] where
cmap = map
cfilter = filter
instance Indexable [] where
atIndex = (!!)
sumOfEvenElements :: (Integral a, Collection c) => c a -> a
sumOfEvenElements c = fold (+) 0 (cfilter even c)现在,sumOfEvenElements接受任何类型的积分集合,并返回该集合中所有偶数元素的和。
发布于 2010-06-27 01:41:59
首先:标准的OO设计在Haskell中不能很好地工作。你可以与语言作斗争,并尝试制作类似的东西,但这将是一次挫折中的练习。所以第一步是寻找风格的解决方案,而不是寻找用Haskell编写OOP风格的解决方案的方法。
但这说起来容易做起来难!从哪里开始呢?
因此,让我们拆解一下OOP为我们做些什么的细节,并考虑一下这些细节在Haskell中可能是什么样子。
protected或internal成员相比较。map的参数发生了翻转。如果您将它应用于一组Int,您将得到一个(Int -> b) -> [b]类型的函数。在某种意义上,您给出的列表仍然“在那里”,但是除了通过函数之外,没有其他东西可以使用它。这可以与OOP成员相媲美,并且被部分应用的原始函数可以与OOP风格的constructor.相媲美
fold函数,它概括了几乎所有的迭代循环、列表转换和线性递归functions.sort的类型为(Ord a) => [a] -> [a];它与您提供的类型的细节完全解耦,除非它必须是实现具有多个类型和共享接口的Ord.
捕获的行为
您可能还会发现this blog post很有帮助;它快速总结了您将在Haskell中使用什么来解决一些标准设计模式在OOP中经常用于解决的问题。
作为最后的补充,作为一名C#程序员,您可能会发现研究它与Haskell之间的联系是很有趣的。相当多的负责C#的人也是Haskell程序员,最近C#中的一些新成员受到了Haskell的很大影响。最值得注意的可能是LINQ底层的一元结构,IEnumerable本质上是list monad。
发布于 2010-06-27 01:30:33
Haskell使用抽象数据类型,而不是类和对象。在构建和观察信息的组织方式问题上,这确实是两种兼容的观点。在这个问题上,我所知道的最好的帮助是威廉·库克的论文“Object-Oriented Programming Versus Abstract Data Types”。他有一些非常清楚的解释,大意是
库克的论文将向你展示一个很好的抽象矩阵布局,并教你如何将任何类组织为ADY,反之亦然。
类层次结构还包含一个元素:通过继承重用实现。在Haskell中,这种重用是通过第一类函数实现的:Primate抽象中的函数是一个值,Human抽象的实现可以重用Primate抽象的任何函数,可以包装它们以修改其结果,等等。
在使用类层次结构的设计和使用抽象数据类型的设计之间没有一个完全合适的。如果您试图从一个音译到另一个音译,您将得到一些笨拙而不地道的东西-有点像用Java编写的FORTRAN程序。但是,如果您理解类层次结构的原则和抽象数据类型的原则,您就可以采用一种风格来解决问题,而在另一种风格中为同样的问题设计一个相当得体的解决方案。这确实需要练习。
附录:也可以使用Haskell的类型类系统来模拟类层次结构,但那是另一回事。类型类与普通类足够相似,以至于许多标准示例都可以工作,但它们又有很大的不同,可能会有一些非常大的意外和不匹配。虽然类型类对于Haskell程序员来说是一个无价的工具,但我建议任何学习Haskell的人学习使用抽象数据类型来设计程序。
https://stackoverflow.com/questions/3124511
复制相似问题