F#type obj但我想'a

Oma*_*lak 4 recursion f# functional-programming list

我定义了一种类型

type 'a sexp =
| E of 'a
| T of ( sexp<'a> * sexp<'a> );;
Run Code Online (Sandbox Code Playgroud)

例:

("this".(("是"."a").("s"."表达")))

是一个字符串的性别.

((1.5).2)

是一个int的性别.


我创建了一个函数tolist,给定一个表达式返回一个格式的列表.

let rec tolist expr =
match expr with
| Null -> [" "]
| E(x) -> [string x]
| T(l,r) -> 
    let l = tolist l
    let r = tolist r
    ["("]@(l)@[" . "]@(r)@[")"];;
Run Code Online (Sandbox Code Playgroud)

val tolist:expr:obj sexp - > string list

我的问题是我想要'一个性别而不是一个obj sexp就像告诉我的那样.我哪里做错了?

一个电话就像那个叫(T(E("this"),E("是")));;

rmu*_*unn 5

stringF#中函数的类型obj -> string,所以它的约束类型x在你的E(x)obj.(更新:它稍微复杂一些;请参阅本答案的后半部分以了解所有细节.但它归结为" string需要在编译时知道其参数的具体类型,以便它可以调用正确的.ToString()方法.如果你传递一个泛型类型,它可以肯定的唯一具体类型是obj,所以它最终会限制你的泛型类型obj.")而这反过来又限制你的tolist函数的类型sexp<obj>(或者obj sexp - 相同的类型,不同的写作方式).

如果您改为使用替换string呼叫sprintf "%A",则您的功能将是正确的通用.例如,您希望代码看起来像这样:

type 'a sexp =
| E of 'a
| T of ( sexp<'a> * sexp<'a> )

let rec tolist expr =
    match expr with
    | Null -> [" "]
    | E(x) -> [sprintf "%A" x]
    | T(l,r) -> 
        let l = tolist l
        let r = tolist r
        ["("]@(l)@[" . "]@(r)@[")"]
Run Code Online (Sandbox Code Playgroud)