mam Producer
który tworzy wartości, które zależą od przypadkowości, wykorzystując własne Random
monady:Jak mogę idiomatycznie i wydajnie spożywać fajkę w monadzie innej niż IO z operacją IO?
policies :: Producer (Policy s a) Random x
Random
jest opakowaniem nad mwc-random
, które mogą być uruchamiane z ST
lub IO
:
newtype Random a =
Random (forall m. PrimMonad m => Gen (PrimState m) -> m a)
runIO :: Random a -> IO a
runIO (Random r) = MWC.withSystemRandom (r @ IO)
policies
producent otrzymuje lepsze i lepsze zasady z prostego algorytmu uczenia zbrojenia.
mogę skutecznie po wykreślić politykę, powiedzmy, 5.000.000 iteracje przez indeksowanie w policies
:
Just convergedPolicy <- Random.runIO $ Pipes.index 5000000 policies
plotPolicy convergedPolicy "policy.svg"
I teraz chce wykreślić pośrednie polityki na każdym 500000 kroków, aby zobaczyć, jak one zbieżne. Napisałem kilka funkcji, które pobierają producent policies
i wyodrębniają listę ([Policy s a]
) z, powiedzmy, 10 zasad - po jednej na 500 000 iteracji - a następnie wykreślają wszystkie z nich.
Jednak te funkcje zajmują dużo więcej czasu (10x) i zużywają więcej pamięci (4x) niż tylko kreślenie ostatecznej polityki, jak wyżej, mimo że całkowita liczba iteracji uczenia się powinna być taka sama (np. 5 000 000). Podejrzewam, że to z powodu wydobywania listę hamującą śmieciarza, a to wydaje się być unidiomatic zastosowanie Rury
Idiomatic rury styl zużywa natychmiast elementów, ponieważ są one generowane zamiast ładuje wszystkie elementy w pamięci .
Co to jest prawidłowe podejście do spożywania rurę tak, gdy Producer
jest nad jakimś losowym monady (tj Random
) i efekt chcę produkować jest w IO
?
Innymi słowy, chcę podłączyć Producer (Policy s a) Random x
do Consumer (Policy s a) IO x
.
Czy 'Random' ma instancję' MonadIO'? Jeśli tak, będziesz mieć 'hoist liftIO :: Consumer (Policy s a) IO x -> Consumer (Policy s a) Random x'. Są na to inne sposoby, niektóre mogą być szybsze, ale może pomóc dowiedzieć się więcej o 'Losowym'. – Michael
@Michael: Nie ma i nie chcę tego. Może jedynie wykonywać losowość i * nie * ogólne IO. Idealnie, chciałbym rozwiązanie, które zależy tylko od tego, że 'Random' ma funkcję' runIO :: Random a -> IO a'. –
I chyba nie chcesz, aby 'hoist runIO' konwertował' Producer (Policy s a) Random x' na 'Producer (Policy s a) IO x' ze względu na sposób generowania losowości. – Michael