Я был очень впечатлен библиотекой FSharpPlus и тем, как она позволяет эмулировать некоторые общие классы типов.Но я действительно верю в силу отделения экземпляра класса типов от определения типа, поэтому я пытался создать концептуальное подтверждение использования некоторых из тех же методов, что и FSharpPlus, но рассматривая экземпляр класса типов как совершенно отдельныйюридическое лицо.Честно говоря, я немного расширяю свои возможности SRTP, и источник FSharpPlus находится немного над моей головой.Вот моя попытка на данный момент:
module Monad =
let inline bind (m:^Monad) (f:'a -> '``Monad<'b>``) (x:'``Monad<'a>``) : '``Monad<'b>`` =
(^Monad : (member Bind : _*_ -> _) (m, f, x))
let inline rtn (m:^Monad) (source:'a) : '``Monad<'a>`` =
(^Monad : (member Return : _ -> _) (m, source))
type ListMonad = ListMonad with
member this.Bind (f, x) = List.collect f x
member this.Return x = [x]
type OptionMonad = OptionMonad with
member this.Bind (f, x) = Option.bind f x
member this.Return x = Some x
Это позволяет мне делать некоторые базовые вещи, но я врезаюсь в стену, как только пытаюсь использовать bind
дважды в одной функции:
let inline applyFromMonad (monadInstance) (f:'``Monad<'a -> 'b>) (x:'``Monad<'a>``) : '``Monad<'b>`` =
f |> Monad.bind monadInstance (fun f' ->
x |> Monad.bind monadInstance (fun a' ->
Monad.rtn monadInstance (f' a')))
(я буду беспокоиться о реализации выражений вычислений позже).Проблема в том, что компилятор ожидает, что f'
и a'
будут того же типа , предположительно потому, что Monad.bind
не рассматривается как достаточно универсальный.Вместо параметра f
функции связывания, обрабатываемой как функция, принимающая любой универсальный тип 'a, он обрабатывается как функция, принимающая некоторый конкретный тип в функции applyFromMonad
.Есть ли способ обойти это так, чтобы bind
можно было задавать аргументы разных типов при двойном вызове?
Конечно, весь этот вопрос был бы спорным, если этот запрос на извлечение превращает его вязык, но мне не хватает понимания, чтобы знать, если это произойдет в ближайшее время.Возможно, мой ответ, однако, будет ждать этой функции ...
И, конечно, если есть другой подход, который достигнет той же цели (классы типов с отдельным экземпляром класса типов из определения типа, с сигнатурами, которые будутобычно для правильного определения нужны типы с более высоким родом), я с удовольствием рассмотрю что-то другое.