Циклическая функция / тип зависимости в F#

У меня есть вопрос о том, как лучше поступить следующим

У меня есть класс B, у меня есть комбинатор на B, пусть foo: B -> int.

Я хочу, чтобы в классе B комбинатор был инкапсулирован как метод, поэтому я добавляю его с расширением типа.

Позже я потом понимаю, что foo довольно дорогой и хочу кешировать его результат с ленивой оценкой

Поэтому я добавляю в систему огромное сцепление, передавая комбинатор как функцию конструктору, а затем инициализируя поле с помощью foo = lazy(foo self) в конструкторе.

т.е.

type foo =
    class
        val x : int Lazy

         new (comb) as self = {x=lazy(comb self);}
     end
 let something (x:foo) = 1

 type foo with
      new() = foo(something)

это явно не так

две опции, которые я вижу для исправления этого: 1, сделать интерфейс и иметь foo наследовать этот интерфейс, 2, сделать все статическим методом, а затем сделать комбинаторы из этих статических методов (что-то вроде противоположности их присоединения к классам...)

Ни один из них не очень привлекателен, и мне было интересно, если я пропустил вариант 3

О, и я не смог получить let rec и работать с этим совершенно правильно, и я бы не хотел, чтобы "что-то" в приведенном выше утверждении зависело от функции, которая зависит от функции, которая зависит от функции (3 глубоких).

Любой совет будет принят во внимание

2 ответа

Решение

Я не думаю, что с вашим текущим дизайном что-то не так. Ключевым моментом является то, что если вы определяете тип Foo а также расширение типа в том же файле (и в том же модуле), тогда F# объединит две части определения в один тип.NET. Таким образом, тот факт, что он определен в двух отдельных частях, является лишь деталью реализации.

Если вы не хотите показывать конструктор, который принимает комбинатор, вы можете пометить его как private, Вместе с несколькими дополнительными изменениями (т. Е. С использованием неявного синтаксиса конструктора) фрагмент будет выглядеть следующим образом:

type Foo private (comb) as self =
  let x : Lazy<int> = lazy comb self

let something (x:Foo) = 1

type Foo with
  new() = Foo(something)

Если вы хотите сохранить something как отдельная функция, то это прекрасное решение. Многие числовые типы в F# PowerPack следуют этому шаблону (см., Например, определение комплексных чисел).

Я не совсем понимаю, что вы ищете, но я думаю, что это может помочь:

type foo(comb) as self =
    let x = lazy(comb self)
    static member something (x:foo) = 1 
    new() = foo(foo.something)

Тип может быть рекурсивным со своим собственным статическим членом, так что это более простой способ написания кода.

Другие вопросы по тегам