Komonadka Cofree
jest przydatna do iterowania funkcji częściowych w sposób polimorficzny dla typu błędu. Jego coiter
przypomina forM
-zachowanie w monadzie błędu, ale zbiera wygenerowane wartości w sposób czysty/leniwy i widzisz tylko błąd na końcu, w strukturze danych.Czy istnieje ogólny sposób na dekomponowanie darmowego comonada przez monadę awarii w "strumieniu wartości i ostatecznym błędzie"?
Na przykład Cofree Identity
(bez awarii dozwolone!) Jest nieskończony strumień, natomiast Cofree Maybe
jest izomorficzna NonEmpty
i Cofree (Either e) a
jest w zasadzie (NonEmpty a, e)
(lista wartości udany-iteracji plus błąd, który pojawia się na końcu).
Teraz zastanawiam się, jaki jest najlepszy sposób oceny wyników, bez konkretnego dopasowania wzorców w monadach pojedynczego błędu. Wyodrębnianie wszystkich wartości jest bardzo łatwe dzięki instancji Foldable
(np.), ale nie jestem pewien, jak najlepiej uchwycić błędy . Byłoby to możliwe do wykorzystania Foldable
na to, aby po prostu pozbyć z wartości i pozostawić część błędzie:
vals'n'err :: (Monad m, Foldable m)
=> Cofree m a -> (NonEmpty a, (m()))
vals'n'err (a :< q) = case toList q of
[] -> (a:|[], const() <$> q)
l -> first (pure a<>)
$ foldr1 (\(bs,e) (cs,f) -> (bs<>cs, e>>f)) $ vals'n'err<$>l
ale czuje się trochę hackish. Czy istnieje lepsze rozwiązanie?
Od konstruktywny POV uzyskiwanie '(niepusty A, E)' z 'Cofree (albo E) a 'nie ma dla mnie większego sensu, ponieważ' Cofree' jest typem koincypcyjnym i całkiem dobrze jest, gdy 'Cofree (Eide e) a' jest nieskończonym strumieniem przeplatanym przez' Right's, ale obiecujesz zawsze zwróć 'e'. Nic dziwnego, że "vals'n'err" wydaje się hackish. – user3237465
@ user3237465: yeah. Więc jaki podpis byś zaproponował? – leftaroundabout
Nie widzę problemu do rozwiązania tutaj. Zużywanie "Cofree (e e) a" w streamingu i zatrzymywanie się na "Left" jest powszechnym i rozsądnym sposobem, dlaczego warto ryzykować, aby uzyskać nieprzeniknioną przeciekającą dno typu 'e'? – user3237465