如何将记录的属性声明为抽象函数

时间:2016-02-12 07:35:06

标签: f#

我是F#和函数式编程的新手,需要一些帮助。我来自c#所以我的心态仍然会受到影响。

我需要将一些选项传递给一个函数,并且我使用了一个记录。其中一个选项是延续功能单元 - >选项<' a取代。我无法弄清楚如何定义记录类型。以下是我一直在尝试的例子。

type Func2<'a> = 'a -> 'a option

type ProcessOptions = {
        func1: int -> int option
        func2: Func2<int>   // This works...
        //func2: Func2<'a>  // ... but this is what I'm trying to achieve - so that I can pass any Func2<'a> using this record.
    }

let f1 a = 
    let r = Some a
    printfn "f1: %A" r |> ignore
    r

let f2 (a:'a) = 
    let r = Some a
    printfn "f2: %A" r |> ignore
    r

let f3 (processOptions:ProcessOptions) = 
    processOptions.func1(3) |> ignore
    processOptions.func2 789 |> ignore
    ()

let f4 (processOptions:ProcessOptions) = 
    processOptions.func1(4) |> ignore
    //processOptions.func2 "abc" |> ignore // as a result this does not work...
    ()

[<EntryPoint>]
let main argv = 

    f1(1) |> ignore
    f2 123 |> ignore
    f2 "abc" |> ignore

    let fo = {
        func1 = f1
        func2 = f2
    }
    f3 fo

    let fo1 = {
        func1 = f1
        func2 = f2
    }
    f4 fo1


    0 

2 个答案:

答案 0 :(得分:1)

在这里你需要使记录具有通用性 - 有点像

type ProcessOptions<'a> = {
        func1: int -> int option

        func2: Func2<'a>  // ... but this is what I'm trying to achieve - so that I can pass any Func2<'a> using this record.
    }

答案 1 :(得分:1)

记录中的成员不能是通用函数(可以使用不同类型的参数调用,例如|int)。它总是有一个固定的类型。

您可以使用的技巧是使用通用方法定义一个简单的接口:

string

现在记录中的成员只能是type Func = abstract Invoke<'a> : 'a -> 'a option 类型(没有泛型类型参数),但Func内的Invoke方法将是通用的:

Func

创建type ProcessOptions = { func1: Func func2: Func } 值比编写普通函数要困难一些,但是你可以使用对象表达式:

Func

您现在可以传递let f1 = { new Func2 with member x.Invoke(a) = let r = Some a printfn "f1: %A" r |> ignore r } 并使用不同类型的参数调用ProcessOptions方法:

Invoke
相关问题