Haskell是否支持面向对象的编程

时间:2011-03-24 03:10:45

标签: haskell

它是否支持声明和实现的分离(Java中的接口和类)等概念?

如何限制访问(如Java中的访问修饰符)?

5 个答案:

答案 0 :(得分:55)

如何在Haskell中分离声明和实现?

在Haskell中你可以定义一个typeclass,它与面向对象的类有很大不同,所以不要让这个名字欺骗你。使用关键字class,您可以声明函数名称和类型签名,可以在其他地方为特定数据类型实例化(实现)。

例如,Hashable类型类定义了hash函数,它可以将任何实例化的数据类型转换为Int。有一个新的,时髦的数据类型,你希望能够哈希?很好,做一个Hashable的例子。最常见的数据类型由定义Hashable的模块实例化(请参阅“实例”的链接文档)。

类型类不是定义接口的唯一方法。经常被低估的方法是普通的旧数据结构。因为Haskell具有第一类函数,所以您可以定义一个具有字段函数的数据结构:

data ShuttleInterface =
  SI { launch    :: Delay -> IO Handle
     , deploy    :: Payload -> IO ()
     , getStatus :: IO Status
     }

您的函数可以构建或使用此数据结构:

deployAllSensors :: ShuttleInterface -> IO ()
deployAllSensors shuttle = do
    status <- getStatus shuttle
    let notDeployed = filter (not . deployed) (sensors status)
    when (isOrbiting status) (mapM_ deploySensor notDeployed)

-- we used the well-known Haskell functions: filter, not, , when, mapM_
-- and some supporting functions were assumed:
isOrbitting :: Status -> Bool
deploySensor :: Sensor -> IO ()
sensors :: Status -> [Sensor]
deployed :: Sensor -> Bool

如何限制对Haskell中数据的访问?

为了提供抽象,Haskell使用Algebraic Data Types。为了保护字段,开发人员声明了一种数据类型,但是没有导出它的构造函数 - 相反,它们只导出一组维护所需不变量的安全基元。

例如,Map模块提供了一个平衡树。如果任何人只能使用BranchLeaf的原语来声明地图,则无法保证平衡,因此制造商不会将其导出。构建映射必须依赖于从Data.Map导出的内容(以及那些可以通过在同一模块中访问/使用构造函数的内容),例如fromListempty,{{1和一大堆修饰符。

答案 1 :(得分:20)

请参阅Oleg Kiselyov和Ralf Laemmel的Haskell's Overlooked Object System,详细解释如何在Haskell中实现OO概念。但正如Antal在评论中所说,不要试图在Haskell中编写Java程序。

请记住,对象是一个穷人的封闭,封闭是一个穷人的对象。

答案 2 :(得分:5)

类型类确实是在OO概念上远程提醒的唯一构造 - 在这种情况下,在接口上。但是,与java不同,类型类不是类型。

关于类型类的一个好处是我可以创建一个完全不相关的,已经存在的类型类的成员。而在java中,有时人们会认为:这些来自包org.a的类A和来自com.b的B我应该使用的应该是第三个包实现接口Y,但没有办法做到不需要许多样板代码,附加间接,编组等。

BTW,作为一名老年程序员,我想指出“声明和实施的分离”本身与OOP无关。仅仅因为大多数OO-languga支持它并不意味着在OO发明之前这个概念在很长一段时间内并不为人所知。感兴趣的年轻人如果认为在OO主流化之前编程必须处于“石器时代”水平,可能会查找MODULA,例如,声明和实施的分离不仅是可能的,而且是由语言强制执行的。

答案 3 :(得分:2)

值得一提的是lenses。它们允许你写出a.b.c.d.e&#34;表达式#34;以一种可以组合的方式。

可以为每个数据结构定义.。所以在某种意义上,.是Haskell的一等公民。它可以命名,存储,两个. - s可以组成,等等。

答案 4 :(得分:0)

我只是偶然发现了某事,请参阅https://github.com/complyue/ooh,以了解具有完整机器的可运行程序(尽管完整代码仍然非常短)。

我从没想过 OO 时尚的程序可以用 Haskel 编写 如此直截了当!

构造对象:

!o <- classC $^ (777, "hahah")

调用直接方法:

  cx0 <- o $. getNumC $ ()
  o $. setNumC $ 888

调用基本方法:

  bx0 <- (o $.. cast'C'as'B) getNumB ()
  (o $.. cast'C'as'B) setNumB 999

方法参数必须像这里原型那样未使用,我想它是 不过,在编写 OO 样式代码时会具有更好的风味。

虽然目前看来手工制作的对象类定义很冗长, 我相信 Template Haskell 可以提供很多更好的语法糖。