在类型别名中重用类型别名

时间:2019-04-10 09:29:53

标签: f#

所以那天我看到...给我留下了深刻的印象

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

(我知道这个例子有点愚蠢) 关键是可以在类型别名中捕获复杂的参数约束。...很好

然后我开始使用此功能,但是到了需要使用Bar的功能的地步

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

所以我们有

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

但是后来我想要一个Foo,它返回了一个酒吧。...所以我可以去...。(我认为)

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,我当然可以做到。...

即类型别名为我提供了我想要的机制,但是似乎没有简单的方法来构成类型别名,而又不用重新定义顶级别名中的所有约束。

在这种情况下还可以。...但是对于大量参数,它变得越来越繁琐。

所以... 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)

0 个答案:

没有答案