Код Cofree
comonad полезен для итерации частичных функций способом, который является полиморфным по типу ошибки. Его coiter
напоминает forM
-looping в monad ошибки, но он собирает полученные значения чистым/ленивым способом, и вы видите только ошибку в конце, вниз в структуре данных.Существует ли общий способ разложения бесплатного comonad над модой отказа в «поток значений и конечную ошибку»?
Например, Cofree Identity
(неисправность не допускается!) Бесконечный поток, в то время как Cofree Maybe
изоморфна NonEmpty
и Cofree (Either e) a
в основном (NonEmpty a, e)
(список значений преуспевающего-итерационных плюс ошибка, которая происходит в конце).
Теперь я задаюсь вопросом, что является лучшим способом для оценки результатов, без определенного соответствия шаблонов на одной монаде ошибок. Извлечение всех значений очень просто благодаря экземпляру Foldable
(например, toList
), но я не уверен, как наилучшим образом получить ошибки . Можно было бы использовать Foldable
для этого, чтобы просто получить избавиться значений и оставить часть ошибки:
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
, но это чувствует себя немного хака. Есть ли лучшее решение?
От конструктивного POV получать '(NonEmpty а, е)' из 'косвободным (или е) a 'не имеет для меня большого смысла, так как' Cofree' является коиндуктивным типом, и вполне нормально для 'Cofree (или e) a' быть бесконечным потоком, чередующимся« Right's », но вы обещаете всегда верните 'e'. Не удивительно, что «vals'n'err» чувствует себя взломанным. – user3237465
@ user3237465: да. Итак, какую подпись вы предложили бы? – leftaroundabout
Я не вижу здесь проблемы. Потребление «Cofree (или e) a» потоковым способом и остановка на «левом» - это общий и разумный способ пойти, зачем рисковать получить нечеткое утечку дна типа 'e'? – user3237465