引数として他の関数 ( などdisplay
) に渡される関数は、F# でそれ自体を多態的にすることはできません。ジェネリック型パラメーター ('a
など) を使用できますが、このパラメーターの実際の型は、メイン関数 (このNotWorking
場合) が呼び出されるときに指定されます。これは、本体のdisplay
型変数に使用される単一の実際の型でのみ呼び出すことができることを意味します。'a
NotWorking
回避策として、ジェネリック メソッドでインターフェイスを使用できます。
type Displayer =
abstract Display : (obj -> unit) -> 'T list -> unit
let NotWorking (display:Displayer) =
display.Display (printfn "%O") [1;2;3]
display.Display (printfn "%O") ["a";"b";"c"]
インターフェイスのメソッドDisplay
はそれ自体がジェネリック メソッドであるため、そのメソッドを異なる型引数で複数回呼び出すことができます (int
最初のケースとstring
2 番目のケース)。
ただし、F#で通常のコードを頻繁に記述する場合、これが制限であるとは思いませんでした。そのため、問題に対するより簡単な解決策があるかもしれません(おそらく、非ジェネリックIEnumerable
またはそのような単純なものを使用する-またはobj list
Johnからの回答のように) )。実際のコードの詳細を教えていただけると助かります。
理論的な詳細に興味がある場合に備えて、いくつかの背景を説明しますが、これらはどれも、日常の実際の F# プログラミングで重要になるものではありません。ともかく -
これは Haskell のような他の言語で可能であり、それを可能にするメカニズムはユニバーサル タイプと呼ばれます。F# にポリモーフィック関数がある場合、それは基本的に、型変数のスコープが関数全体であることを意味するため('a -> unit) -> unit
、forall 'a . ('a -> unit) -> unit
.
関数を呼び出すときは、'a
変更できないものと変更できないものを指定する必要があります (つまり、一度'a -> unit
に 2 つの異なる型を引数として取得した関数を使用することはできません)。'a
'a
ユニバーサル型を使用するforall
と、自分で書くことができるので、その型は: であると言えます
(forall 'a . 'a -> unit) -> unit
。これで、ジェネリック パラメーター'a
は、引数として取得する関数にのみリンクされます。引数として指定された関数の型は、それ自体が汎用関数になったため、 を表すさまざまな型で呼び出すことができます'a
。
PS: 値の制限は別の問題です。つまり、基本的に、F# は構文関数ではないものをジェネリックにすることはできませんが、この例では構文関数を記述しているため、ここでは問題になりません。