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
F# 在F中使用类型和整数约束进行设计#_F#_Ocaml - Fatal编程技术网

F# 在F中使用类型和整数约束进行设计#

F# 在F中使用类型和整数约束进行设计#,f#,ocaml,F#,Ocaml,如何在F#中设计一个整数类型,该类型初始化为0,并且有一些方法总是单调地增加值,即第一次调用该方法返回1,第二次调用2等 下面是OCAML代码,描述了我希望在F中实现的功能# 您可以将其直接转换为类型(在ML中也可以): 当然,它可能不是性能最好的,因此您可能会选择这样的方式(也更接近您的版本): 遗憾的是,F#没有Ocaml拥有的强大模块,因此我在这里修复了int 通用版本 如果您真的想要,您可以让它更通用一些: module Term = type T<'a> =

如何在F#中设计一个整数类型,该类型初始化为0,并且有一些方法总是单调地增加值,即第一次调用该方法返回1,第二次调用2等

下面是OCAML代码,描述了我希望在F中实现的功能#


您可以将其直接转换为类型(在ML中也可以):

当然,它可能不是性能最好的,因此您可能会选择这样的方式(也更接近您的版本):

遗憾的是,F#没有Ocaml拥有的强大模块,因此我在这里修复了
int

通用版本 如果您真的想要,您可以让它更通用一些:

module Term =

    type T<'a> = 
        private T of 'a with
        override x.ToString () = 
            match x with 
            | (T i) -> i.ToString()


    let inline init ()      = T LanguagePrimitives.GenericZero
    let inline succ (T i)   = T (i + LanguagePrimitives.GenericOne)
    let compare (T a) (T b) = compare a b
    let getValue (T i)      = i
将按预期工作:

> let one = Term.init () |> Term.succ;;
val one : Term.T<int>

> let two = Term.succ one;;
val two : Term.T<int>

> one = Term.succ (Term.init ());;
val it : bool = true

> one < two;;
val it : bool = true

> one >= two;;
val it : bool = false

> compare one two;;
val it : int = -1
>让one=Term.init()|>Term.such;;
val一:术语
>设二=项。成功一;;
val二:术语
>一=Term.such(Term.init());;
val it:bool=true
>一小于二;;
val it:bool=true
>一个>=两个;;
val-it:bool=false
>比较两者;;
val it:int=-1
如果您关心结构/值类型 按照@vandroys的回答或进行以下微调:

module Term =

    type [<Struct>] T<'a> internal (a : 'a) = 
        member internal __.value = a

    let inline init ()         = T (LanguagePrimitives.GenericZero)
    let inline succ (i : T<_>) = T (i.value + LanguagePrimitives.GenericOne)
模块术语=

type[]T最小值类型实现:

type [<Struct>] Term private (i : int) =
    member __.Value = i
    member __.Next = Term (i + 1)
    // optional static members
    static member Zero = Term ()
    static member value (t : Term) = t.Value
    static member next  (t : Term) = t.Next
这种方法的泛化不允许下一个
实例成员(静态成员可以),因为类型上不支持F#的成员约束。如果这是一个要求,我也会考虑一个<代码>内部< /代码>构造函数,或者使用单元素DU允许模块私有构造的方法。
如果有人来这里只是寻找一个返回递增整数的函数,Str在问题的注释中暗示的是:

不幸的是,F#并不完全支持ML样式的模块(或函子)。现有答案涵盖了使用惯用F#处理某些情况的方法,这些情况下可以使用现有模块,但受到相当的限制

一个更忠实、但不那么惯用、更麻烦的翻译可能看起来更像这样:

type TermRec<'t> = {
    succ: 't -> 't
    init: unit -> 't
    compare: 't -> 't -> int
}

type TermUser<'z> =
    abstract Use : TermRec<'t> -> 'z

type Term =
    abstract Apply : TermUser<'z> -> 'z

let mkTerm r = { new Term with member this.Apply(u) = u.Use r }

let term1 = mkTerm { succ = (fun i -> i + 1); init = (fun() -> 0); compare = compare }

let term2 = mkTerm { succ = (fun i -> not i); init = (fun() -> false); compare = compare }

let user = { 
    new TermUser<_> with 
        member this.Use(t) = 
            t.compare (t.init() |> t.succ |> t.succ) (t.init()) }

let v1 = term1.Apply user
let v2 = term2.Apply user
类型TermRec't
初始:单位->'t
比较:'t->'t->int
}
键入TermUser->'z
类型术语=
摘要适用:术语用户i+1);init=(fun()->0);比较=比较}
让term2=mkTerm{such=(fun i->not i);init=(fun()->false);compare=compare}
让用户={
新用户
成员。使用(t)=
t、 比较(t.init()|>t.such |>t.such)(t.init())}
设v1=term1。应用用户
设v2=term2。应用用户
请特别注意:

  • 完全支持具有不同类型参数的术语(
    int
    s、
    bool
    s等)
  • 术语隐藏其基础
    TermRec
    的类型参数,并且会泄漏此类型值的用户将不会编译(尽管您可以创建一个
    TermUser
    ,它使用.NET反射在运行时中断封装并返回例如类型的字符串名称)

  • 如果我理解正确,并且您希望创建一个函数,该函数每次被调用时都提供一个新值,那么通常的解决方案是使用计数器的ref并将其保持为私有。在OCaml中,代码是:

    let create_counter initial_value =
      let counter = ref initial_value in
      fun () ->
        let result = !counter in
        incr counter;
        result
    
    其用途如下:

    # let new_id = create_counter 0;;
    val new_id : unit -> int = <fun>
    # new_id ();;
    - : int = 0
    # new_id ();;
    - : int = 1
    # new_id ();;
    - : int = 2
    # new_id ();;
    - : int = 3
    
    #让新的_id=create_计数器0;;
    val new_id:unit->int=
    #新的_id();;
    -:int=0
    #新的_id();;
    -:int=1
    #新的_id();;
    -:int=2
    #新的_id();;
    -:int=3
    
    谢谢。我将尝试一下,看看泛型版本如何工作。如果你想放弃花哨的类型工作,一个int-ref的闭包就可以了。
    module Term =
    
        type [<Struct>] T<'a> internal (a : 'a) = 
            member internal __.value = a
    
        let inline init ()         = T (LanguagePrimitives.GenericZero)
        let inline succ (i : T<_>) = T (i.value + LanguagePrimitives.GenericOne)
    
    type [<Struct>] Term private (i : int) =
        member __.Value = i
        member __.Next = Term (i + 1)
        // optional static members
        static member Zero = Term ()
        static member value (t : Term) = t.Value
        static member next  (t : Term) = t.Next
    
    Term.Zero.Next = (Term.Zero |> Term.next) // true
    Term.Zero < Term.Zero.Next                // true
    
    /// Returns 1 on first call, otherwise last issued + 1
    let intSource =
        let i = ref 0
        fun () -> incr i; i
    
    type TermRec<'t> = {
        succ: 't -> 't
        init: unit -> 't
        compare: 't -> 't -> int
    }
    
    type TermUser<'z> =
        abstract Use : TermRec<'t> -> 'z
    
    type Term =
        abstract Apply : TermUser<'z> -> 'z
    
    let mkTerm r = { new Term with member this.Apply(u) = u.Use r }
    
    let term1 = mkTerm { succ = (fun i -> i + 1); init = (fun() -> 0); compare = compare }
    
    let term2 = mkTerm { succ = (fun i -> not i); init = (fun() -> false); compare = compare }
    
    let user = { 
        new TermUser<_> with 
            member this.Use(t) = 
                t.compare (t.init() |> t.succ |> t.succ) (t.init()) }
    
    let v1 = term1.Apply user
    let v2 = term2.Apply user
    
    let create_counter initial_value =
      let counter = ref initial_value in
      fun () ->
        let result = !counter in
        incr counter;
        result
    
    # let new_id = create_counter 0;;
    val new_id : unit -> int = <fun>
    # new_id ();;
    - : int = 0
    # new_id ();;
    - : int = 1
    # new_id ();;
    - : int = 2
    # new_id ();;
    - : int = 3