Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types F中自然数的类型级编码#_Types_F#_Inline_Type Level Computation - Fatal编程技术网

Types F中自然数的类型级编码#

Types F中自然数的类型级编码#,types,f#,inline,type-level-computation,Types,F#,Inline,Type Level Computation,我试图将自然数编码为F#中的一种类型,以便能够在编译时而不是运行时检查等式。我能想出的最好办法就是 type Nat<'T> = abstract member AsInt : int type Z() = interface Nat<Z> with member __.AsInt = 0 type S<'P>(prev : Nat<'P>) = interface Nat<S<'P>

我试图将自然数编码为F#中的一种类型,以便能够在编译时而不是运行时检查等式。我能想出的最好办法就是

type Nat<'T> =
    abstract member AsInt : int

type Z() = 
    interface Nat<Z> with 
        member __.AsInt = 0

type S<'P>(prev : Nat<'P>) =
    interface Nat<S<'P>> with 
        member __.AsInt = 1 + prev.AsInt

type TNat =
    static member zero = Z() :> Nat<Z>
    static member succ (prev : Nat<'P>) = S(prev) :> Nat<S<'P>> 
    static member one = TNat.succ(TNat.zero)
    static member two = TNat.succ(TNat.one)
使用
成员_uuu.AsInt=1+prev.AsInt
TNat型=
静态成员zero=Z():>Nat
静态成员成功(上一个:Nat>
静态成员1=TNat.succ(TNat.zero)
静态成员2=TNat.succ(TNat.one)
我不确定我对代码是否满意。是否可以用我忽略的更好(或更容易)的方式来完成


我可以确保
AsInt
是在编译时计算的吗?

在您的代码中,如果您尝试:

TNat.two = TNat.succ(TNat.one)
将产生错误

下面是一个没有接口的替代实现:

type Z = Z with
    static member (!!) Z = 0     

type S<'a> = S of 'a with
    static member inline (!!)  (S a) = !!a + 1

let inline asInt x = !! x

let one = S Z
let two = S one
类型Z=Z,带有
静态成员(!!)Z=0

类型F#type系统允许您执行一点类型级别的编程,但不是很多-因此我认为这种方法不会很好地工作(如果您想将其用于实际的事情).您尝试这样做的背景是什么?我想创建一个工具来计算一系列值的第n个矩,并能够组合部分结果。我认为在编译时检查我不能组合不同的矩会很好。计算的矩在编译时是固定的,高阶矩是固定的最不需要的。除此之外还有好奇心:-)这听起来确实是一个非常有趣的用例。我想你可以(用你所拥有的)让它工作起来,虽然语法不会更漂亮。您也可以为类似的东西编写类型提供程序,例如,
时刻
——这也扩展了类型系统,但可能会更好。请参阅,谢谢您的提示。事实上,考虑到更好的语法,我想我更喜欢类型提供程序,并会尝试它们。谢谢。
不是(TNat.two=TNat.succ(TNat.one))
确实很难看。我想我需要一个接口来调用
(!!)
,但在您的版本中,我可以简单地内联以获得静态成员约束,即
让内联asInt(n:'T)=!!n
。是的,我使用一个中间运算符让编译器自动推断静态约束。然后,当我定义nice asInt函数时,约束会被传播。你也可以去掉该运算符,手工编写约束。我非常喜欢这个解决方案,但是有没有办法有效地包装
S
Z
返回到一个
NatNum
类型,就像一个有区别的联合?当然,只需更改
(!!)
的实现即可返回DU。