在Haskell中处理复杂组合的POD(OO中的普通旧数据)的推荐方法是什么?

Eon*_*nil 3 haskell pod

我是Haskell的新手.

在静态类型的OO语言(例如,Java)中,所有复杂的数据结构都表示为类和实例.对象可以具有许多属性(字段).另一个对象可以是该字段的值.可以使用其名称访问这些字段,并按类静态键入.最后,这些对象构建了彼此链接的巨大对象图.大多数程序都使用这样的数据图.

如何在Haskell中归档这些功能?

Ant*_*sky 5

如果你真的有没有行为的数据,这很好地映射到Haskell记录:

data Person = Person { name    :: String
                     , address :: String }
            deriving (Eq, Read, Show)

data Department = Management | Accounting | IT | Programming
                deriving (Eq, Read, Show)

data Employee = Employee   { identity   :: Person
                           , idNumber   :: Int
                           , department :: Department }
              | Contractor { identity :: Person
                           , company  :: String }
              deriving (Eq, Read, Show)
Run Code Online (Sandbox Code Playgroud)

这表示a PersonPerson谁拥有nameaddress(两者都是String); 一个Department或者是Management,Accounting,IT,或Programming; 和Employee或者是一个Employee谁具有identity(一Person)中,idNumber(一个Int),以及department(A Department),或者是一个Contractor谁具有identity(一Person)和company(A String).这些deriving (Eq, Read, Show)行使您可以比较这些对象是否相等,读取它们并将它们转换为字符串.

通常,Haskell数据类型是联合(也称为sum)和元组(也称为产品)的组合.1|小号表示选择(联合):一个Employee或者一个Employee或一个Contractor,一个Department是四件事情等.通常,元组被写入类似以下之一:

data Process = Process String Int
Run Code Online (Sandbox Code Playgroud)

这说明Process(除了是一个类型名称)是一个带有类型的数据构造函数String -> Int -> Process.因此,例如Process "init" 1,或Process "ls" 57300.A Process必须同时存在StringInt存在.上面使用的记录符号只是这些产品的语法糖; 我也可以写data Person = Person String String,然后定义

name :: Person -> String
name (Person n _) = n

address :: Person -> String
address (Person _ a) = a
Run Code Online (Sandbox Code Playgroud)

但是,记录符号对于复杂的数据结构来说可能很好.

另请注意,您可以将Haskell类型与其他类型进行参数化; 例如,一个三维点可能是data Point3 a = Point3 a a a.这意味着Point3 :: a -> a -> a -> Point3 a,所以人们可以写Point3 (3 :: Int) (4 :: Int) (5 :: Int)一个Point3 Int,或者Point3 (1.1 :: Double) (2.2 :: Double) (3.3 :: Double)得到一个Point3 Double.(或者,如果您已经看过类型类和重载的数字文字,那么Point3 1 2 3获得一个Num a => Point3 a.)

这是表示数据图表所需的内容.但是,请注意:人们从命令式语言转换为功能性语言的一个问题 - 或者实际上,在任何两种不同的范例之间(C到Python,Prolog到Ruby,Erlang到Java,等等) - 继续尝试解决问题旧的方式.您尝试建模的解决方案可能无法以易于编程技术的方式构建,即使问题是这样.例如,在Haskell中,考虑类型非常重要,其方式与Java不同.与此同时,对于那些类型实施的行为是非常不同的做法:高阶函数捕捉一些你在Java中已经看到了抽象的,但也有一些这是不容易表达(map :: (a -> b) -> [a] -> [b],filter :: (a -> Bool) -> [a] -> [a],和foldr :: (a -> b -> b) -> b -> [a] -> b浮现在脑海中).因此,请保持您的选择开放,并考虑以功能性方式解决您的问题.当然,在这种情况下,也许你可以全力以赴.但是在探索新语言时请记住这一点.玩得开心 :-)


1:递归:例如,你可以表示二叉树data Tree a = Leaf a | Branch a (Tree a) (Tree a).