повторное использование псевдонимов типов в псевдонимах типов

#f#

#f#

Вопрос:

Итак, я был весьма впечатлен на днях, когда увидел…

 type Foo<'a> = 
   abstract foo : Unit -> 'a
type IsFoo<'a,'b when 'a :> Foo<'b>> = 'a
  

(Я знаю, что этот пример немного глупый)
дело в том, что сложные параметрические ограничения могут быть зафиксированы в псевдониме типа …. приятно

Затем я начал использовать это немного, но я дошел до того, что у меня есть функция, для которой требуется панель

 type Bar<'b> = 
    abstract bar : Unit -> 'b
  

итак, мы имеем

 type IsBar<'a,'b when 'a :> Bar<'b>> = 'a
  

но тогда я хотел Foo, который возвращал Bar….so Я МОГ бы пойти….(Я думаю)

 type IsFooThenBar<'a,'b,'c when 'a :> Foo<'b> and 'b :> Bar<'c>> = 
    IsFoo<'a,IsBar<'b,'c>>
  

но это своего рода просто повторное изложение того, что я уже знаю … на самом деле мне бы очень хотелось, чтобы ограничение было выведено, т.е.

 type IsFooThenBar2<'a,'b,'c> = IsFoo<'a,IsBar<'b,'c>>
  

но это явно не работает, потому что компилятор жалуется, что я не могу утверждать IsFoo и IsBar, если у меня нет необходимых ограничений…

есть идеи?….У меня много общих ограничений на мой код, и они не очень хорошо сочетаются с объявлениями типов.

чтобы уточнить, основываясь на некоторых отзывах, как я могу взять набор псевдонимов типов и скомпоновать их в более сложные, не просто пересчитывая их …. т. е. Я хочу иметь возможность исправить один из аксиоматических псевдонимов и отразить его в производных псевдонимах, без множества, множества и множестваввод текста.

итак, делая это конкретным, я могу написать

 let f (x : IsFoo<_,IsBar<_,string>>) = 
    x.foo().bar()
  

что в простых случаях нормально … но помните, что у меня много-много параметров…

поэтому я действительно хочу упростить это и написать…

 let f2 (x : IsFooThenBar<_,_,string>) = 
    x.foo().bar()
  

и я, конечно, могу это сделать, если я определю IsFooThenBar, как описано выше….

т.Е. псевдонимы типов дают мне механизм, который я хочу, но, похоже, нет простого способа составить псевдонимы типов без повторного указания всех ограничений в псевдониме верхнего уровня.

в данном случае это нормально …. но для большого количества параметров это становится все более и более обременительным.

So…an примером языка, на котором вы можете делать подобные вещи, является Haskell…

 > class Foo a b | a -> b where
>     foo :: a -> b
>     
> class Bar a b | a -> b where
>     bar :: a -> b

> class (Foo foo bar,Bar bar a) => FooThenBar foo bar a where
  

Затем я могу использовать FooThenBar в качестве краткого указания, что существуют функции, которые сопоставляют ‘foo с ‘bar и ‘bar с любым типом, который я укажу

(Я не эксперт по Haskell и должен был получить помощь для создания этого слабо эквивалентного сценария)

это оригинальная функция

 > f :: (Bar bar b, Foo foo bar) => foo -> b
> f x = bar (foo x)
  

и при этом используется новая предполагаемая композиция

 > f' :: (FooThenBar foo bar b) => foo -> b
> f' x = bar (foo x)
  

Комментарии:

1. Разве это не может быть просто IsFooThenBar<'a, 'b, 'c when 'a :> Foo<'b> and 'b :> Bar<'c>> = 'a ? Это позволяет избежать повторного утверждения.

2. Также стоит указать, если вы не знаете, это <'a when 'a :> X> можно упростить как <#X> (если вам не нужен дескриптор 'a ). Так что, если бы вы хотели let f (x:IsFoo<_, Foo<int>>) = ... , вы могли бы просто написать let f (x:#Foo<int>) = ... . И let f (x:IsFooThenBar<_, Foo<_>, Bar<int>>) = ... может быть let f (x:#Foo<#Bar<int>>) = ...

3. см.: learn.microsoft.com/en-us/dotnet/fsharp/language-reference/…

4. мои примеры trivial…so Я знаю, что могу сделать полное заявление, дело в том, что если у меня есть псевдонимы, которые накладывают атомарные ограничения, могу ли я скомпоновать их в более сложные… без простого их пересчета

5. таким образом, «IsFooThenBar<‘a, ‘b, ‘c, когда ‘a :> Foo<‘b> и ‘b :> Bar<‘c>> = ‘a» переформулирует ограничение для IFoo и IBar… в этом примере они тривиальны, но если бы они были сложными, это было бы болезненно. если IFoo был сложным, и я отредактировал, Id тогда придется редактировать все эти «производные» константы …. это много ввода, который, вероятно, пойдет не так