Каков рекомендуемый способ обработки сложносоставленных POD (простых старых данных в OO) в Haskell? - PullRequest
3 голосов
/ 12 февраля 2011

Я новичок на Хаскеле.

В статически типизированных языках ОО (например, Java) все сложные структуры данных представлены как класс и экземпляры. Объект может иметь много атрибутов (полей). А другим объектом может быть значение поля. Эти поля могут быть доступны по их именам и статически типизированы по классам. Наконец, эти объекты создают огромный граф объектов, которые связаны друг с другом. Большинство программ использует график данных, как это.

Как мне заархивировать эти функции в Haskell?

Ответы [ 2 ]

5 голосов
/ 12 февраля 2011

Если у вас действительно есть данные без поведения, это хорошо сопоставляется с записью на 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)

Это говорит о том, что Person - это Person, у которого есть name и address (оба String с);Department является либо Management, Accounting, IT, либо ProgrammingEmployee является либо Employee, который имеет identity (a Person), idNumber (Int) и department (a Department), либо являетсяContractor, у которого есть identity (Person) и company (String).Строки deriving (Eq, Read, Show) позволяют сравнивать эти объекты на равенство, считывать их и преобразовывать в строки.

В общем случае тип данных Haskell представляет собой комбинацию объединений (также называемых суммы *)1031 *) и кортежи (также называемые products ). 1 | s обозначает выбор (объединение): Employee равно либо an Employee или Contractor, Department - это одна из четырех вещей и т. Д. В общем случае кортежи пишутся примерно так:

data Process = Process String Int

Это говорит о том, что Process (в дополнение кимя типа) является конструктором данных с типом String -> Int -> Process.Так, например, Process "init" 1 или Process "ls" 57300.Process должен иметь и String и Int, чтобы существовать.Запись, использованная выше, является просто синтаксическим сахаром для этих продуктов;Я мог бы также написать data Person = Person String String, а затем определить

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

address :: Person -> String
address (Person _ a) = a

Запись записи, однако, может быть полезна для сложных структур данных.

Также обратите внимание, что вы можете параметризовать тип 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).

1 голос
/ 12 февраля 2011

Haskell имеет алгебраические типы данных, которые могут описывать структуры или объединения структур таким образом, чтобы что-то заданного типа могло содержать один из множества различных наборов полей. Эти поля могут быть установлены и доступны как позиционно, так и через имена с синтаксисом записи.

Смотрите здесь: http://learnyouahaskell.com/making-our-own-types-and-typeclasses

...