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

str*_*der 36 haskell

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

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

Tho*_*son 57

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

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

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

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

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

为了提供抽象,Haskell使用代数数据类型.为了保护字段,开发人员声明数据类型但不导出它的构造函数 - 而是只导出一组维护所需不变量的安全基元.

例如,Map模块提供了一个平衡树.它不能保证平衡,如果有人可以只使用申报的元一个Map BranchLeaf,所以制造商没有出口的.地图的建设必须依靠什么从Data.Map出口(与那些访问/凭借同一模块中被使用的构造函数),例如fromList,empty,singleton,和一大堆的改性剂.

  • +1,也许值得指出的是,由于所有数据都是不可变的,尽管可能,保护字段并不像具有可变数据类型的OOP语言那样重要. (16认同)
  • @Ingo 需要的不是防止修改的能力,而是防止依赖的能力。就像 `sun.misc.Unsafe` 显示的那样。可以说,OOP 是关于抽象内部。 (2认同)

Pau*_*son 22

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

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

  • 您可以将闭包视为单方法ad-hoc对象; 就像一个对象一样,它用一个动态绑定的函数包装了一堆数据,并将使用它.因此对于OO程序员来说,闭包看起来有点像一种非常有限的对象.另一方面,如果你想在Java中创建类似闭包的东西,那么你需要创建一个特殊的基类,然后为每个版本的闭包创建一个新的后代.因此,从功能程序员的角度来看,一个对象看起来像一个非常笨拙和棘手的闭合. (10认同)
  • @PaulJohnson您的链接已损坏.你能给出纸张的实际名称吗? (7认同)
  • 根据@caya 的有用评论,我编辑了评论以包含论文名称和链接。 (2认同)

Ing*_*ngo 6

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

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

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