F# 类型级别数算法
我在和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
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>>