#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 тогда придется редактировать все эти «производные» константы …. это много ввода, который, вероятно, пойдет не так