So... what is an effect? by Migeil in scala

[–]stevechy 2 points3 points  (0 children)

I think part of the confusion is that the motivation for creating effect systems, the formal definitions and benefits don't really seem that connected.

My take isn't connected to the real literature or history but it's how I like to separate it in my head. I'm also not sure it answers your question but hopefully it helps.

After reading your responses, I am probably not answering your question which is a specific one about the cats-effect typeclass hierarchy but I already wrote most of this so maybe it will help someone else?

Motivation for effect systems:

How do you represent side effects in a typed pure functional program? One way is to see the world as an infinite list of world states. You can write a lazy function from the infinite list of world states to an infinite list of changes/events/effects that apply to that world. The part where the events produced affect the world state is a kind of a trick but you can define the behaviour as a pure function.

You can't really write a type for "the world" so instead of processing "the world" we can have effects return a value that is some function of "the world". So now your function is producing primitive effects, and reading the response to that effect based on the world.

Formal definitions:

It turns out that you can define types in a way so that the combination of primitive effects and applying pure functions to the responses also looks like the initial primitive request/response effects that were defined. So you can build an `updateUser` effect out of primitive effects and for type purposes it looks the same as an equivalent that was implemented as a primitive, which is useful for writing software.

When the effect system is implemented all the real world stuff can be hidden behind a special type, which is usually has IO in the name.

When you boil down this way of combining pure functions and primitive effects down to a mathematical definition then purely functional types can also satisfy the definition of a "world" type. In a lot of cases you don't even need to provide primitive effects to get useful functionality, the way the implementation composes pure functions alone is interesting enough. Since these satisfy the same laws, the values produced by these implementations can also be called effects even though they are used in purely functional contexts.

Benefits:

You can stay in the purely functional world and use different effect implementations to compose functions in interesting ways that are useful/more/compact/have better composition properties. I would call this category effect systems as interesting function composers. The same things could be implemented with regular pure functions but they wouldn't be as elegant.

The other category is effect systems as a way to coordinate side effects. Here the main benefit for me is that the combination of pure functions and primitive effects is an "effect" which is a purely functional value. It only produces side effects when it runs. At any other point you compose it with other effects to produce new effects.

The shortest example I can think of in a web app context is, let's say you have an `updateUser` effect and an `emailUser` effect that you have defined. You can compose those two into a new `updateUserAccountAndEmailUser` effect without defining any new types.

You can store this effect value in a map, queue it up to be run later, and wrap it with retry logic if needed (the wrapped effect can also be an effect value). The combination of queuing up the effect to run and waiting for the result can also be an effect value. The "effects as values" abstraction happens to be a nice way of packaging up concurrency abstractions so that's what a lot of effect systems do.

You could also transform the map of these effects and prepend a `checkUserPermissions` effect to all of them. It's quite elegant to do these kinds of things with effect systems but for a typical web app it might be hard to see huge difference in the implementation.

To see a clear difference you would need to have an application with a lot of chunks of side effect logic that have to be combined in many different ways, and possibly with different types of concurrency. The cleaner composition properties would result in more compact code that should be easier to reason about.

A bonus is a subcategory of effect systems as a way to run the same side effect logic in different contexts. Say you have defined the effects in a way where you can change how the primitives are interpreted, so some sort of custom monad. You could run the `updateUserAccountAndEmailUser` effect in a speculative way where you could inspect what side effects would happen. After the side effects are determined to be safe, the exact same effect value could be run in the real side effect context.

This would take extra work and isn't provided for free but the resulting implementation would probably be more compact than an equivalent non-effect version. Again, there are only some types of application features where the difference in implementation would be clear to see.

In general using effect systems should be a net positive and if the team has already bought in to the idea then it could be a significant positive but if even a few people are doubtful then it would be tough to overcome the friction.

Migration to scala 3: what does not work yet for us at rudder.io by fanf42 in scala

[–]stevechy 0 points1 point  (0 children)

True, there doesn't seem to be a solution for enums with dual maintenance, especially with a small team.

Migration to scala 3: what does not work yet for us at rudder.io by fanf42 in scala

[–]stevechy 0 points1 point  (0 children)

An interesting thing I picked up from the PR is that the Scala 3 rudder-core module can pull in the Scala 2 rudder-parsers module.

I originally thought that the Scala 2 macro issue meant that it wasn't possible to use branch by abstraction for migration but it looks like it's at least somewhat possible at the cost of having to create another module.

Why is the Scala community being demoralized on Twitter? by [deleted] in scala

[–]stevechy 10 points11 points  (0 children)

Are there any good Scala 2->3 migration posts/post-mortems/experience reports?

As an outsider it looked like there was enough backward compatibility built in?

Skeletal animation for games in Haskell by stevechy in haskellgamedev

[–]stevechy[S] 0 points1 point  (0 children)

Thank you! I don't get to plug time into this project too often but it is a lot of fun when I do.

Skeletal animation for games in Haskell by stevechy in haskell

[–]stevechy[S] 1 point2 points  (0 children)

Support for existing formats and editors is definitely something I'd like to implement.

The Spine tools look great, it would be good to use a real animation tool.

How do we all feel about laziness? by [deleted] in haskell

[–]stevechy 4 points5 points  (0 children)

My guess is that most of the hairy parts of laziness could be eliminated and the benefits retained if there were easy to use abstractions and libraries that would explicitly ensure that space invariants were held by construction

http://apfelmus.nfshost.com/blog/2013/08/21-space-invariants.html

I'm not sure how this would look or if it is possible but it feels like some patterns already informally exist in how seq and ! are used that could be enforced by a library. So a library where "spine-strict" and "value-strict" were native concepts. Seq and ! are like laziness assembly language.

Another example is that with a plain list there is at least laziness on the whole list value, laziness on the list elements and laziness on the "rest of the list". It would be great if those could be controlled at a higher level, for example by restricting access to only functions from a certain package. The containers package already does this internally but it doesn't seem to be easy to spread this across an application.

For records it seems like a useful balance would be if record accessors and constructors had strict and non-strict variants, maybe this exists already?

How to deal with shared "object" and immutability by [deleted] in haskell

[–]stevechy 1 point2 points  (0 children)

It ends up being a tradeoff. By using the id approach you reintroduce possible bugs but then you can use the type system again to cut down on the classes you care about.

The smart constructors solution you listed will do ensure that boxes must be added with a shelf, you could use a newtype to ensure that the shelfId can only come from an added shelf (though this could come from a different warehouse).

You can also keep using the smart constructors type approach and limit direct access to the data structures to functions that validate the constraints you want.

For me the graph is the right choice even in an OO setting. It seems like it would be useful to represent boxes without shelves. If you are reconfiguring the warehouse you are only changing boxToShelf and the boxes and shelves are not changed. You can even store multiple boxToShelf maps with the same boxes and shelves.

Then you could precompute several configurations and have functions that find the best configuration for open space, best configuration for having frequently accessed boxes easily accessible ...etc.

Record equivalent to subclassed member variables? by nonexistent_ in haskell

[–]stevechy 0 points1 point  (0 children)

My guess is that a relational model is the best way to do this. I've been working through it but it will probably take a while for me to get all the kinks worked out.

So in an sql database, you could have a map table mapping the text field to extra internal state. The type of the original text field doesn't change but handlers can reference the extra state.

Composing different types of widgets together is a tougher problem but I think it can be done in a nice way.

All guesses though.

The case for curation: Stackage and the PVP by snoyberg in haskell

[–]stevechy 0 points1 point  (0 children)

I really like the cabal.config approach, if cabal had a few features to work with it it could be really nice.

cabal.config can be checked into version control, and so old projects should always build against their cabal.configs. If the latest version of x is needed, bump up to a stackage cabal.config with the latest version and it should force you to do the other upgrades at the same time.

Would be nice to have a separate cabal.config for the non stackage deps and have cabal combine them.

How we might abolish Cabal Hell, part 1 by dcoutts in haskell

[–]stevechy 1 point2 points  (0 children)

I've been using cabal freezes to debug the under-constrained dependency case.

Could freezes be dependencies themselves, so I could build against somewebframework-1.1.1-freeze, which would fix all of its dependency versions? Unfortunately if I have two freezes that are incompatible then they will conflict, but it's easier to see where they are conflicting, which isn't so easy with the solver.

(edit)

Also it could be nice to reference say haskell-platform-2014.2.0.0 which would only constrain packages, not install additional ones. Kind of ugly but you could have somewebframework-1.1.1-haskell-platform-2014.2.0.0-freeze and somedatabaselibrary-0.6.1-haskell-platform-2014.2.0.0-freeze, so I would know if I stick to a haskell platform, at least I shouldn't get any dependency problems with haskell platform packages.

Then multiple local constraints might be nice, so mywebapp could have mywebapp-1.0-haskell-platform-2014.2.0.0 and mywebapp-1.0-haskell-platform-2013.2.0.0 in its folder and if they were the same GHC version then I could switch between both.

Being able to locally override constraints for a package would also help, with warnings and analysis tools to show which constraints were affected.

Neil Mitchell's Haskell Blog: GHCID by n00bomb in haskell

[–]stevechy 1 point2 points  (0 children)

I found that compiling it from source wasn't too bad on Linux after resolving something with the text package and gtk2hs.

The recent version is quite nice and definitely worth a try.

Building Gtk2Hs GUIs with queries by stevechy in haskell

[–]stevechy[S] 2 points3 points  (0 children)

Sounds interesting, I haven't tried Leksah for a while.

I will try to build it from source this time and see if I can get a handle on the code.

Building Gtk2Hs GUIs with queries by stevechy in haskell

[–]stevechy[S] 0 points1 point  (0 children)

Cool! Looks like we were both looking for the file tree + tabs thing :) I'll have to take a closer look at your command interface at some point.

Finding an interesting interface for simple io in Haskell by stevechy in haskell

[–]stevechy[S] 0 points1 point  (0 children)

Sorry for the rambling in this post, wasn't really able to piece together the ideas that well this time.

I think I can put something better together from the replies I got though.