truizlop on utilities
truizlop on master
Miscellaneous utilities (#459) … (compare)
truizlop on utilities
Add docs (compare)
truizlop on utilities
Fix wrong documentation Add instances of Semigroup and … Add utility to Kleisli and 2 more (compare)
miguelangel-dev on calvellido-patch-1
miguelangel-dev on master
Fix bad space char at docs (#45… (compare)
Day
is neither correct nor complete. These methods are internal and prepended with an underscore because they are meant to be implemented by internal subclasses of Day
. The public ones come from the instance of Comonad
for Day
.
Moore
I'd be interested in seen this approach
IO
to handle effects as well
Hi everyone 👋
I have a little question, I'm in a case where I want to go from an IO<Error, MyModel?>
to an IO<Never, MyModel?>
when I use the handleError method, I can return a nil, but the ErrorType doesn't switch to Never as I would suppose it should.
Using Apple Combine, the .replaceError
method act like that.
am I missing something ?
func getPeopleAPI(id: Int) -> IO<Never, SWAPIPeopleResponse?> {
var components = URLComponents(string: "https://swapi.co/api/people/\(id)")!
return URLSession.shared
.dataTaskIO(with: components.url(relativeTo: nil)!)
.map { _, data in data }
.map { data in
try? JSONDecoder().decode(SWAPIPeopleResponse?.self, from: data)
}
.handleError({ _ in nil })^
}
handleError
followed by mapError
in order to have Never
as the error type
func getPeopleAPI(id: Int) -> IO<Never, SWAPIPeopleResponse?> {
var components = URLComponents(string: "https://swapi.co/api/people/\(id)")!
URLSession.shared.dataTaskPublisher(for: components.url(relativeTo: nil)!).replaceError(with: <#T##Output##Foundation.URLSession.DataTaskPublisher.Output#>)
return URLSession.shared
.dataTaskIO(with: components.url(relativeTo: nil)!)
.map { _, data in data }
.map { data in
try? JSONDecoder().decode(SWAPIPeopleResponse?.self, from: data)
}
.handleError({ _ in nil })^
.mapLeft({ _ in abort() })
}
on another hand, for me it is weird model your problem like an right-optional (maybe I am, and you want to wrap this network over IO)
you are working with: ERROR + (ERROR + VALUE) = ERROR + ERROR + VALUE, so you can go out with 2 possible errors (one from IO another for Optional - losing the type) - do you think about to change the API to: IO<ApiError, SWAPIPeopleResponse>
@miguelangel-dev you are right, I shouldn't model it like that, for the network call, I should pass the error to the caller (that is what I will do at a later time) but I still need a way (that you 've given me) to go back to a Left Never, because in my redux implementation, I don't want the core implementation to know about errors, errors should be handled early (in the reducer part) to model it as a state published by the store.
I'll show you when I'm done with the whole implementation 🙂
I will change for a fatalError as suggested,
Thanks to you two for your help
Hi Marcelo, it depends on kind the project you are looking for. For now, as OSS, we are working in a refactor in another library from bash to FP in pure Swift. It is nef: https://github.com/bow-swift/nef - and you can find the project using an architecture FP thanks to Bow: https://github.com/bow-swift/nef/tree/develop/project
It is nice because in the same project you can find an example how to make a functional-library (API) and how to use it (CLI) in pure Swift with Bow
hi everyone !
what would be the right way to execute an IO on background queue and get back to main queue to use the result ?
I tried
effect.attempt(on: .global(qos: .background)).unsafeRunAsync(on: .main,
{ resultAction in
print(resultAction)
self.send(resultAction.rightValue) //Should never error out
})
but it seems to block the UIThread
let action = IO<Never, Action>.var()
let sendEffect = binding(
continueOn(.global(qos: .userInitiated)),
action <- effect,
|<-ConsoleIO.print("action is \(action.get)"),
continueOn(.main),
|<-IO.invoke { self.send(action.get) },
yield: ()
)^
try! sendEffect.unsafeRunSync()
attempt
is synchronous. Even though you are passing a different queue to run it, it will block the current queue until it finishes, and then do the unsafeRunAsync
. The second one should work fine if you call sendEffect.unsafeRunAsync
. It is the same reason: it blocks because it is synchronous.