F# 类型级别数算法

F# 类型级别数算法,f#,F#,我在和F#型的推理机玩。试图使类型级别的自然数正常工作 这是我努力工作的部分 type Zero = Zero type Succ<'a> = None type True = True type False = False type IsZero = | IsZero static member instance (IsZero, _ : Succ<'a>, _) = fun () -> False static member i

我在和F#型的推理机玩。试图使类型级别的自然数正常工作

这是我努力工作的部分

type Zero = Zero

type Succ<'a> = None

type True = True

type False = False

type IsZero = 
    | IsZero
    static member instance (IsZero, _ : Succ<'a>, _) = fun () -> False
    static member instance (IsZero, _ : Zero, _) = fun () -> True

module TypeArithmetic = 
    let inline zero x = (Inline.instance (IsZero, x) : unit -> 'a)()
    let dec (_ : Succ<'a>) = Unchecked.defaultof<'a>
    let inc (_ : 'a) = Unchecked.defaultof<Succ<'a>>
和x和y分别正确推断为False和True(a被推断为Succ,b为零)

现在是棘手的部分。我想让函数
添加
。
它需要能够同时接受Succ和Zero,所以我需要再次使用重载hack使其工作

type Add =
    | Add
    static member instance (Add, _ : Zero, _ : Zero, _) = fun () -> Zero
    static member instance (Add, x : Succ<'a>, _ : Zero, _) = fun () -> x
    static member instance (Add, _ : Zero, y : Succ<'a>, _) = fun () -> y
    static member instance (Add, _ : Succ<'a>, _ : Succ<'b>, _) = 
        fun () -> Inline.instance(Add, Unchecked.defaultof<Succ<Succ<'a>>>, Unchecked.defaultof<'b>) ()  
类型添加=
|加
静态成员实例(Add,0:Zero,0:Zero,0)=fun()->Zero
静态成员实例(Add,x:Succ,u)=fun()->y
静态成员实例(添加,成功,成功)=
fun()->Inline.instance(Add,Unchecked.defaultof)()
据我所知,这应该行得通。不是吗?但事实并非如此。我在
Inline.instance
调用中得到一个错误,表示无法使用该点之前给出的信息解决歧义。我有点明白为什么,因为我不在内联函数中,它试图解析为具体类型,但它还没有。但我仍然有一种感觉,我应该能够使它以某种方式工作


有没有办法让它发挥作用

问题是只有一个重载应该匹配

您不需要超过两个,您可以添加零案例和将循环的案例,顺便说一下,应该按照注释中的说明将其标记为内联:

type Add =
    | Add
    static member        instance (Add, _ :Zero    , y   , _) = fun () -> y
    static member inline instance (Add, _ :Succ<'a>, _:'b, _) = fun () -> 
        Inline.instance(Add, Unchecked.defaultof<'a>, Unchecked.defaultof<Succ<'b>>) ()

let inline add x y = Inline.instance (Add, x, y)()
类型添加=
|加
静态成员实例(Add,3;:Zero,y,3;)=fun()->y
静态成员内联实例(添加,\成功)
Inline.instance(添加,未选中.defaultof>)()
让inline add x y=inline.instance(add,x,y)()
但是还有另一个问题,在第二次过载时,它将默认为零,这是从第一次过载推断出来的

解决此问题的一个技巧是添加虚拟重载:

type Add =
    | Add
    static member        instance (Add, _ :Add      , y  , _) = fun () -> y
    static member        instance (Add, _ :Zero     , y  , _) = fun () -> y
    static member inline instance (Add, _ :Succ<'a> ,_:'b, _) = fun () -> 
        Inline.instance(Add, Unchecked.defaultof<'a>, Unchecked.defaultof<Succ<'b>>) ()

let inline add x y = Inline.instance (Add, x, y)()
类型添加=
|加
静态成员实例(Add,3;:Add,y,3;)=fun()->y
静态成员实例(Add,3;:Zero,y,3;)=fun()->y
静态成员内联实例(添加,\成功)
Inline.instance(添加,未选中.defaultof>)()
让inline add x y=inline.instance(add,x,y)()
这样,它就不会默认为零,因为它不能在编译时被推断出来

不久前,我也使用了重载运算符和模式匹配

更新

您不需要第二个参数是多态的,这也可以完成以下工作:

type Add =
    | Add
    static member        instance (Add, _ :Add     , _) = id
    static member        instance (Add, _ :Zero    , _) = id
    static member inline instance (Add, _ :Succ<'a>, _) = fun (_:'b) -> 
        Inline.instance(Add, Unchecked.defaultof<'a>) Unchecked.defaultof<Succ<'b>>
类型添加=
|加
静态成员实例(添加,添加,添加)=id
静态成员实例(Add,0:Zero,0)=id
静态成员内联实例(添加,\成功)
Inline.instance(添加,未选中.defaultof>

您的实现与我的实现之间存在一些差异(参见链接)但我不会使用内联帮助器,至少它是在FsControl中定义的,因为它是专门为基于返回类型的推断而设计的。

我不太明白如何调用
Add
,但将最后一个函数标记为内联解决了眼前的问题。@JohnPalmer你认为有机会吗?这是一个很好的d技巧嗯,当我尝试使用add函数时,这个推论对我来说仍然不起作用。
让x=Zero |>inc |>inc |>inc;让y=Zero |>inc |>inc |>inc |>inc |>inc |>inc;让z=add y
值限制。
值'z'哈s被推断为具有泛型类型val z:Succ>when(添加或零或Succ或^ a):(静态成员实例:添加*Zero*Succ*^ a->unit->a)将“z”定义为一个简单的数据项,使其成为一个带有显式参数的函数,或者,如果您不希望它是泛型的,则添加一个类型注释
@LukaHorvat我明白了,但这是一个值限制,这是一个小问题,有很多方法可以解决它,例如,如果您使用z做其他事情,它将消失,例如:try添加这一行
让z_plus_1=inc z
哦。好的。除了在某个地方使用它或添加显式类型之外,还有其他方法修复它吗?@LukaHorvat是的,我简化了函数,现在它不见了,请参阅更新的代码。
type Add =
    | Add
    static member        instance (Add, _ :Add     , _) = id
    static member        instance (Add, _ :Zero    , _) = id
    static member inline instance (Add, _ :Succ<'a>, _) = fun (_:'b) -> 
        Inline.instance(Add, Unchecked.defaultof<'a>) Unchecked.defaultof<Succ<'b>>