Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Oct 09 2019 10:41
    iboss-ptk synchronize #460
  • Oct 09 2019 10:21
    iboss-ptk edited #460
  • Oct 09 2019 10:21
    iboss-ptk edited #460
  • Oct 09 2019 10:20
    iboss-ptk opened #460
  • Oct 09 2019 09:58

    truizlop on utilities

    (compare)

  • Oct 09 2019 09:58

    truizlop on master

    Miscellaneous utilities (#459) … (compare)

  • Oct 09 2019 09:58
    truizlop closed #459
  • Oct 09 2019 07:53
    truizlop review_requested #459
  • Oct 09 2019 07:53
    truizlop review_requested #459
  • Oct 09 2019 07:53
    truizlop opened #459
  • Oct 09 2019 07:53

    truizlop on utilities

    Add docs (compare)

  • Oct 09 2019 07:52

    truizlop on utilities

    Fix wrong documentation Add instances of Semigroup and … Add utility to Kleisli and 2 more (compare)

  • Oct 09 2019 07:03
    truizlop commented #448
  • Oct 09 2019 01:34
    iboss-ptk commented #448
  • Oct 09 2019 01:28
    iboss-ptk commented #448
  • Oct 08 2019 10:42

    miguelangel-dev on calvellido-patch-1

    (compare)

  • Oct 08 2019 10:42

    miguelangel-dev on master

    Fix bad space char at docs (#45… (compare)

  • Oct 08 2019 10:42
    miguelangel-dev closed #458
  • Oct 08 2019 10:42
    miguelangel-dev commented #458
  • Oct 08 2019 10:39
    calvellido edited #458
Tomás Ruiz-López
@truizlop
I can create an structure with the dependencies I am going to need
struct Env {
    let database: Storage
    let api: API
}
Then, I can write a function with the following signature:
func cacheUser(byId userId: Int) -> ReaderT<IOPartial<Never>, Env, Bool> which means: "Give me a user ID, and I will return a Reader that, when provided an Env will have all it needs to produce IO<Never, Bool>"
func cacheUser(byId userId: Int) -> ReaderT<IOPartial<Never>, Env, Bool> {
    return ReaderT<IOPartial<Never>, Env, Env>.ask()
        .map { env in env.api.fetch(byId: userId) }
        .flatMap { io in
            ReaderT { env in io.flatMap { user in env.database.save(user) } }
        }^
}
Tomás Ruiz-López
@truizlop
Finally, you can run this function by passing an Env for production, or another one for testing:
let result = try! cacheUser(byId: 1234)
    .invoke(Env(database: StorageImpl(),
                api: APIImpl()))^
    .unsafePerformIO()
Sébastien Drode
@Dragna
ok I wasn't reasoning about that the right way
I was Thinking of the reader as a Big environment that I had to pass around to my functions
Thank you for your help, I will play with that and see what I can do with it :)
Tomás Ruiz-López
@truizlop
for Writer and State, is quite similar but considering that you can append things to the Env (Writer), or set/get things in the Env (State)
Sébastien Drode
@Dragna
so If I wanted a structure that act like an elm component, State would be the best choice ? something that take an action coming from the UI and run it against the current state to return a new state
Tomás Ruiz-López
@truizlop
most likely
for an example of State, I have a sample in a repo
let me check
Sébastien Drode
@Dragna
and I saw on the last commit that you have a new syntax for monad comprehensions, it seems better than the old one :)
Tomás Ruiz-López
@truizlop
yes, that will come in the next version and I think it will make things a looot easier to write
from that line on, you can see how I use State to track the inputs and outputs to see the Console has the right interactions
the repo might be outdated though, I'll try to update it when I'm back from vacation
Sébastien Drode
@Dragna
ok thank you for your help, I will play with all the informations you gave me :)
Tomás Ruiz-López
@truizlop
You’re welcome! Feel free to ask if you find any issue
Thang Mai
@mxth
 let o1 = Option.some(1)
 let o2 = Option.some(2)
 let o3 = Option.map(o1, o2, { $0 + $1 })
I couldn't make it work, getting Cannot convert value of type 'Option<Int>' to expected argument type 'Kind<ForOption, _>'. I'm new to swift & bow, please help.
Sébastien Drode
@Dragna
maybe the compiler isn't able to infer the type of o3, try like that :
let o1 = Option.some(1)
let o2 = Option.some(2)
let o3 = Option<Int>.map(o1, o2, { $0 + $1 })
Tomás Ruiz-López
@truizlop
Exactly what Sebastien says. You can also do
ForOption.map(o1, o2, +)
Thang Mai
@mxth
It works, thanks guys :)
Sébastien Drode
@Dragna
Hello, I was wondering about something, when should someone need to create a new type of monad ? What I want to do is create a data store (kind of like a redux store) where I can act on state if needed to pass it to subcomponent of a swift UI screen.
I was wondering if this was one of the use cases or not.
Tomás Ruiz-López
@truizlop
I think this is similar to what @bkase was doing with comonadic UIs.
Monads serve to chain dependent computations and need to obey some rules, so whenever you have that need and can fulfill such rules, you can create a new type with a Monad instance
Sébastien Drode
@Dragna
ok, I will look into what @bkase did. Thank you for your answer :)
Tomás Ruiz-López
@truizlop
In any case, post your progress and we can help you
Sébastien Drode
@Dragna
👍
balrajOla
@balrajOla

Hi @truizlop , I was playing around with Bow_Swift and trying to figure out where to use which effect. I have a particular scenario as follows:-

struct User {

    let id: String

    let name: String

}



protocol Storage {

    func get(_ id: String) -> IO<Never, User>

    func save(_ user: User) -> IO<Never, Bool>

}



protocol API {

    func fetch(byId: Int) -> IO<Never, User>

}



struct UserUsecase {

    func getUser(byID id: String) -> What kind of effect can I use here? {

        // Get the data from storage



        // return the cached data



        // fetch the data from API



        // save or update the user data from API response



        // return back the latest user info

    }

}

The above function getUserbyID first gets the user data from cache returns that value and in parallel fetched data from API and updates cache and returns back the updates value.

This particular scenario comes a lot in Mobile client application where we cache and update the data from external source.

So What kind of Effect or return type to use here. As any return type can only return once. The only way I can think of is to use Rx Stream. Do we have any other solution or effect to achieve this in a better way?

Tomás Ruiz-López
@truizlop
Hi @balrajOla, as you mention, functions can only return one value, and IO only produces one value. So, as I see it, you have a couple of options:
  • getUser(byId:) could return a tuple of (cache: IO<Never, User>, network: IO<Never, User>). Remember that both are suspended and nothing is really executed until you call unsafePerforIO or unsafeRunAsync. That way, you can return both.
  • Use ObservableK<Never, User> to stream multiple values. There is a wrapper over RxSwift that makes it compatible with all abstractions provided in Bow. This lets you publish multiple values (cached, network...) from a single call, and then send a termination event.
    There will eventually be a wrapper over Combine once it gets stable that will let you do something like with Observable.
balrajOla
@balrajOla
Thanks @truizlop both the solutions mentioned above do solve the problem. But with the first option responsibility to perform both the IO operations goes to the caller of the function and in the second option this works as stream of data. My thoughts are more inclined towards the second option but do you have any example where would the 1st option have more advantage than the second.
Tomás Ruiz-López
@truizlop
In the first option the caller has fine grained detail about several things: where data is coming from (caller may disregard cache and always prefer fresh data from network), caller knows that there are at most two values coming (whereas in Observable you don't know how many values you can expect), you can type the errors differently (IO<DBError, User>, IO<HTTPError, User>). In this case there is a trade off of the details you want to hide and expose as an API to the caller.
balrajOla
@balrajOla
@truizlop Sure that is a good argument..
balrajOla
@balrajOla
@truizlop Do we have any performance measures.. Like when we build expressions by combining smaller expressions and defer the implementation to the end.. What are the pros and cons in terms of performance/ memory in SWIFT. I know in Kotlin building large expressions had lot of stack build ups hence we use coroutines which is kind of work around to reduce memory buildups from stack to heap. But is there any study in Swift.
Tomás Ruiz-López
@truizlop
We haven't done anything like that yet. I am aware that some implementations in Bow are not stack safe. In terms of performance, it would be nice if someone could come up with some benchmark and get some data.
Sébastien Drode
@Dragna
congrats for the release of 0.6.0 🥳
Tomás Ruiz-López
@truizlop
Thanks!
Giovanni Catania
@Gioevi_twitter
Congratulations!
Tomás Ruiz-López
@truizlop
Thanks!
Just a reminder, if you are taking part in the Hacktoberfest and want to contribute to the project, we have some issues tagged for that purpose, but not limited to that. If you read the docs and find a typo or something that can be explained in a better way, that’s also very valuable
Barry Moore
@chiroptical
Hello @truizlop, my name is Barry. I am really new to swift, but I have been doing Haskell for about a year now. I am looking at this project for the Hacktoberfest stuff. However, reading over the contribution guidelines it seems that OSX is required?
Tomás Ruiz-López
@truizlop
yes, you will need Xcode to work with the project
I know there is some support to work from Linux, but I have never tried it myself, so I cannot help in that regard
Barry Moore
@chiroptical
I see. I only own Linux machines and it looks a bit painful to get it working. I'll have to pass unfortunately.
Tomás Ruiz-López
@truizlop
sorry to hear that, but thanks for your interest anyways! if you happen to look at the documentation or API reference and there is something that you think can be improved, that is also a nice way of contributing
Devesh Shetty
@devesh-shetty
Hey team,
Should Tuple * classes be part of bow core rather than optics? That way we could have it for bow and bow optics
Tomás Ruiz-López
@truizlop
Is there any functionality that you need to add for tuples in the core module?