我有一个Option
类型:
type Option<'a> =
| Some of 'a
| None
override x.ToString() = sprintf "%A" x
printf "%A" None // "None"
printf "%A" (Some 1) // "Some 1"
据说,在一个函数中我想打印Some 1
,但在另一个函数中我想打印它的case-identifier,即Some
(丢弃“1”值)。我该怎么办?
答案 0 :(得分:3)
如果你想要一种通用的方法,而不是为你的每个类型实现一个成员,你可以使用反射:
open Microsoft.FSharp.Reflection
let caseLabel<'t> (x: 't) =
let typ = typeof<'t>
if FSharpType.IsUnion(typ)
then
let case, _ = FSharpValue.GetUnionFields(x, typ)
Some case.Name
else
None
答案 1 :(得分:1)
你可以使用匹配:
public function viewUser(Request $request){
$user = User::where('id', $request->id)->first();
$langs = Language::all();
$children = Child::where('user_id', $request->id)->get();
$usrlang = DB::table('language_user')->where('user_id', $request->id)->get();
$usrhob = DB::table('user_hobbies')->where('user_id', $request->id)->get();
$userCh = [];
$userLang = [];
$userHobby = [];
$chLang = [];
$chHobby = [];
foreach ($usrlang as $language){
$userLang[] = $language;
}
foreach ($usrhob as $hobby){
$userHobby[] = $hobby;
}
foreach ($children as $child){
$userCh[] = $child;
$languagesCh = DB::table('child_language')->where('child_id', $child->id)->get();
$hobbiesCh = DB::table('child_language')->where('child_id', $child->id)->get();
foreach ($languagesCh as $chL){
$chLang[] = $chL;
}
foreach ($hobbiesCh as $chH){
$chHobby[] = $chH;
}
}
return view('detail', compact('user','langs', 'children', 'usrlang', 'usrhob', 'userCh', 'userLang', 'userHobby', 'chHobby', 'chLang'));
}
解决你的评论: 在这种情况下,我不会覆盖ToString方法,而是根据预期的行为进行单独的匹配。或者只是定义一个辅助函数来打印选项而不指定内容;
override x.ToString() =
match x with
| Some _ -> "Some"
| None -> "None"
通过这种方式,您可以使用let printEmpty myOpt =
match myOpt with
| Some _ -> "Some"
| None -> "None"
打印内容,也可以使用sprintf "%A" myOpt
进行打印。
答案 2 :(得分:1)
对于它的价值,我将@ scrwtp的版本包含在“类型扩展”形式中,而不是Option&lt;'a&gt;的原始重新实现。理由只是最近定义的类型混淆了在ToString部分中使用caseLabel(原始问题中的Option&lt;'a&gt;定义类型)。
NB。因为我们不能从DU继承(它没有构造函数),所以我们不能重载ToString。因此,ToString的扩展仍然默认为原始的ToString。因此,静态模块样式可能更合适,因为我们可以显式访问新行为。否则,sprintf / printf的行为将访问原始的ToString,这不是我们想要的问题。我认为这是一个编译器错误。错误归档here
顺便说一下:FSI漂亮打印可以缓解仅适用于FSI的情况(TBD)。open Microsoft.FSharp.Reflection
let caseLabel (x:'x) =
typeof<'x> |> fun typ ->
if FSharpType.IsUnion(typ)
then FSharpValue.GetUnionFields(x, typ) ||> fun case _ -> Some(case.Name)
else None
type Option<'t> with
static member toString x =
match caseLabel x with
| Some(label) -> label
| None -> "None"
sprintf "%s" <| (Some 1 |> Option.toString) // returns "Some"
sprintf "%s" <| (None |> Option.toString) // returns "None"