Skip to content

WIP: Towards pure FP using IO Monads and Kleisli composition #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from

Conversation

sentenza
Copy link
Owner

The objective is to refactor the current program in order to be executed only at the end of the world and to enclose the IO side effects into an IO Monad, while composing functions using Kleisli Composition.

Changes proposed in this Pull Request:

  • Split the project into three subprojects:
    • End of the World
    • Application
    • FP library
  • Try to create a point-free program (Tacit programming)
  • Describe the program using function composition
  • Execute the program only at the end of the world
  • Define Monad and KleisliComposition

Notes

Considerations/Implementation Details (optional)

Give enough context to reviewers and specify focus of the changes.

Test Instructions

Explain what was and wasn't tested. Justify why there were no tests.

QA

Screenshots/Screencasts (optional, but should be included when relevant)

@sentenza sentenza added enhancement New feature or request help wanted Extra attention is needed labels Oct 24, 2019
@sentenza sentenza self-assigned this Oct 24, 2019
// val ac = ab `;` bc
implicit final class InfixNotationForPointFree[A, B](private val ab: A => B) extends AnyVal {
// Alias: In Haskell compose is a simple dot
@inline def `.`[C](bc: B => C): A => C = PointFree.compose(ab, bc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be simply

@inline def `.`[C](bc: B => C): A => C = bc.compose(ab)

?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also be very careful with this choice, since the . is already integral part of the language syntax, the risk of creating confusion seems to me too high for the benefit gained.

Also considering that compose and andThen are already in the stdlib.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that it would be a better choice to use andThen and avoid the aliasing for dot. Again, this was just left behind as a trace of what I was trying to do.

@ivanopagano
Copy link
Contributor

If I may say, I'm generally unconvinced about the gained benefits of defining custom versions of the popular combinators/datatypes.

I'm not trying to criticise just for the sake of it. I'm reasoning that the usefulness of having a library that provides such functional affordances is in the breadth of such apis.
While educationally very useful, re-writing custom versions of Kleisli or function composition, tailored for the specific use cases, doesn't actually payback wrt the added complexity and implementation cost.

Using an fp lib like "cats/scalaz" provides a very broad spectrum of previously unavailable functionalities, that concurs to enable a consistent and terse syntax to powerfully combine operations. I think that those are necessary to express a side-effecting program in such a way that it's worth paying the price of the added abstraction.

Just adding food for thought, please consider how the proposal might actually make it less clear what is the real benefit of going to such length, only to express something that seemed so simple before. The risk is that people trying to approach fp, could be actually unconvinced by all the added ceremony with no blatantly clear benefits.

@sentenza
Copy link
Owner Author

sentenza commented Oct 30, 2019

If I may say, I'm generally unconvinced about the gained benefits of defining custom versions of the popular combinators/datatypes.

First things first let me thank you for the time you have spent going through this PR. As you can see in the title of the PR this is a Work In Progress, and its purpose is just educational for now. My idea was to introduce a clear distinction between the description of the program and its execution.

I'm not trying to criticise just for the sake of it. I'm reasoning that the usefulness of having a library that provides such functional affordances is in the breadth of such apis.
While educationally very useful, re-writing custom versions of Kleisli or function composition, tailored for the specific use cases, doesn't actually payback wrt the added complexity and implementation cost.

I know that this is not really useful in a production environment and I wouldn't use this approach in a real project, but quite the opposite.

Using an fp lib like "cats/scalaz" provides a very broad spectrum of previously unavailable functionalities, that concurs to enable a consistent and terse syntax to powerfully combine operations. I think that those are necessary to express a side-effecting program in such a way that it's worth paying the price of the added abstraction.

Keep in mind that a development rule of this project is that

Each implemented piece of code must not have any external dependency

I like the approach expressed in Cats more than anything else, and my idea was actually to introduce some of the fundamental concepts of that library through a direct link from the simpler code that you can find in here. I think that introducing the Category Theory using simple examples helps a lot in the process of switching from the imperative to the functional paradigm.

The real aim of this little project is to bring more people to Scala and FP. That's its sole purpose, so there's no chance to use it apart from in a well confined space made for learning some principle which can be then extended.

Just adding food for thought, please consider how the proposal might actually make it less clear what is the real benefit of going to such length, only to express something that seemed so simple before. The risk is that people trying to approach fp, could be actually unconvinced by all the added ceremony with no blatantly clear benefits.

That's a very good point indeed. I don't really want to scare people, and I can leave this piece of code out of scope. I also think that these subjects are hard to grasp for a newcomer at first, and that it takes time and effort to understand why we should embrace the functional paradigm and its ceremonies.

@ivanopagano
Copy link
Contributor

Thanks for the answer
I think I got your point better now.

I'm conscious of the problem with FP in Scala that justifying the effort undertaken on a very basic use cases becomes hard, yet using the full power of all combinators and type classes becomes overwhelming for those unfamiliar, thus keeping people at a distance in both cases.
For the first it seems that unneeded complexity is introduced for little gain, for the second there are too many things to learn at once which turns into an impossible task.
I guess it's hard to strike a good balance there.

@sentenza
Copy link
Owner Author

I'm conscious of the problem with FP in Scala that justifying the effort undertaken on a very basic use cases becomes hard, yet using the full power of all combinators and type classes becomes overwhelming for those unfamiliar, thus keeping people at a distance in both cases.
For the first it seems that unneeded complexity is introduced for little gain, for the second there are too many things to learn at once which turns into an impossible task.
I guess it's hard to strike a good balance there.

I totally agree on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants