Что ближе всего к Haskell GADT и классам типов в F#?

F# — это ML с ООП. Что ближе всего к обобщенным алгебраическим типам данных и классам типов Haskell?


person mcandre    schedule 09.11.2012    source источник


Ответы (2)


Ответ зависит от того, какую проблему вы пытаетесь решить. В F# нет классов типов и GADT, поэтому прямого сопоставления нет. Однако в F# есть различные механизмы, которые можно использовать для решения проблем, которые обычно решаются в Haskell с помощью GADT и классов типов:

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

  • Если вы хотите написать общий числовой код, вы можете использовать статические ограничения членов (вот пример), который, вероятно, технически наиболее близок к классам типов.

  • Если вы хотите написать более сложный общий код (например, универсальный принтер или синтаксический анализатор), вы часто можете использовать мощные возможности отражения во время выполнения F#.

  • Если вам нужно параметризовать код с помощью набора функций (которые выполняют различные подоперации, требуемые кодом), вы можете обойти реализацию интерфейса, как показывает @pad.

Существует также способ эмулировать классы типов Haskell в F#, но обычно это не идиоматическое решение F#, потому что стиль программирования F# во многом отличается от стиля Haskell. Однако одним из довольно стандартных способов использования этого является определение перегруженных операторов (см. этот ответ SO).

На метауровне вопрос о том, что является эквивалентом функции X на другом языке, часто приводит к запутанному обсуждению, поскольку X может использоваться для решения задач A, B, C на одном языке, в то время как другой язык может предоставлять другие функции для решения одних и тех же проблем (или некоторых проблем может вообще не быть).

person Tomas Petricek    schedule 09.11.2012

В F# часто используются интерфейсы и наследование для этих целей.

Для примера приведем простой класс типов, использующий интерфейсы и выражения объектов:

/// Typeclass
type MathOps<'T> =
    abstract member Add : 'T -> 'T -> 'T
    abstract member Mul : 'T -> 'T -> 'T

/// An instance for int
let mathInt = 
    { new MathOps<int> with
       member __.Add x y = x + y
       member __.Mul x y = x * y }

/// An instance for float
let mathFloat = 
    { new MathOps<float> with
       member __.Add x y = x + y
       member __.Mul x y = x * y }

let XtimesYplusZ (ops: MathOps<'T>) x y z =
    ops.Add (ops.Mul x y) z

printfn "%d" (XtimesYplusZ mathInt 3 4 1)
printfn "%f" (XtimesYplusZ mathFloat 3.0 4.0 1.0)

Это может выглядеть не очень красиво, но это F#-ишный способ сделать это. Для более похожего на Haskell решения, в котором используется словарь операций, вы можете взглянуть на этот хороший ответ< /а>.

person pad    schedule 09.11.2012
comment
Это вводящий в заблуждение пример, потому что для числового кода вы можете просто написать let inline XtimesYplusZ x y z = (x * y) + z, а XtimesYplusZ 3 4 1 и XtimesYplusZ 3.0 4.0 1.0 будут работать. Но, конечно, в другом сценарии код, основанный на стиле, который вы демонстрируете, был бы хорошим способом моделирования такого рода параметризации с помощью операций. Я думаю, это то, что я имею в виду, говоря, что существуют разные подходы к разным проблемам, решаемым классами типов в Haskell. - person Tomas Petricek; 10.11.2012
comment
Да, я изо всех сил пытался найти хороший пример. Я хотел бы продемонстрировать только стиль кодирования; дело не в числовом коде. - person pad; 10.11.2012
comment
Не понял. Вы просто используете дженерики. - person Leo Cavalcante; 30.12.2018
comment
@LeoCavalcante, вот статья на Haskell, объясняющая эту идею: haskellforall.com /2012/05/scrap-your-type-classes.html По сути, вы можете взять сигнатуру с использованием класса типов (Monad m) =› [ma] -› m [a] и преобразовать ее в сигнатуру обычного значения MonadWitness m -> [ma] -> m [a] и полностью обходите программирование на уровне типов, если вы хотите явно передать свидетельство. - person Maximilian Wilson; 24.04.2020