Chcę utworzyć DSL gdzie 2 (foo
i bar
) funkcje mogą być wywoływane z rzędu, dzięki czemuJak utworzyć DSL typesafe dla funkcji przeplatanej wzywa
initialize()
|> foo 10
|> bar "A"
|> foo 20
|> bar "B"
|> transform
to działa całkiem doskonały definiując
type FooResult = FooResult
type BarResult = BarResult
let foo param (result_type:BarResult, result) = (FooResult, transform param result)
let bar param (result_type:FooResult, result) = (BarResult, transform param result)
teraz jednak chcę, aby umożliwić również, że wiele bar
połączenia mogą być wykonywane z rzędu jednak foo
wciąż muszą być wywołana tylko raz
initialize()
|> foo 10
|> bar "A"
//OK
|> bar "B"
|> transform
initialize()
|> foo 10
|> bar "A"
|> foo 20
//should yield an compile error
|> foo 30
|> bar "B"
|> transform
W języku C# mogłem przeciążać bar
, aby zaakceptować BarResult lub FooResult, ale to nie działa dla F #. Przynajmniej nie łatwo. Próbowałem też stworzyć związki dyskryminacyjne, ale naprawdę nie mogę się z tym pogodzić.
wow! Muszę przyznać, że nie myślałem w kategoriach interfejsów - ale nawet gdyby tak było, na pewno nie wymyśliłbym takiego rozwiązania. Czy uważasz, że możliwe byłoby również rozwiązanie z dyskryminującymi związkami? – robkuz
Nie jestem pewien, czy DU zadziałają - kluczową tu metodą jest wykorzystanie relacji dziedziczenia między interfejsami (gdzie dwa różne typy są kompatybilne). Przypuszczam, że 'inline' i przeciążanie może być alternatywą. –
Jeszcze jedno pytanie. Jakie jest znaczenie hasha w 'MarkedValue <#IBarInput, _>'? – robkuz