Skip to content
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

Remove RecursiveTailRecM, move stack safety checks into MonadLaws - f… #1370

Merged
merged 4 commits into from
Sep 19, 2016

Conversation

adelbertc
Copy link
Contributor

@adelbertc adelbertc commented Sep 12, 2016

…ixes #1278 and fixes #1283

cc @johnynek @non

@adelbertc
Copy link
Contributor Author

Hm it seems it fails for Future in the JS tests since you need to Await on the Future to test for equality, but that gets tricky in JS land.. is there any way around this?

@@ -138,7 +132,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable {
* enough, this will work
*/
final def foldMapUnsafe[M[_]](f: FunctionK[S, M])(implicit M: Monad[M]): M[A] =
foldMap[M](f)(M, RecursiveTailRecM.create)
foldMap[M](f)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should foldMapUnsafe be deprecated then?

Copy link
Contributor

Choose a reason for hiding this comment

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

this should just be removed if you ask me. I doubt anyone is using it and removing RecursiveTailRecM is at least as big of an issue.

@kailuowang
Copy link
Contributor

Should the unsafe defaultTailrecM be removed?
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/Monad.scala#L24

@non
Copy link
Contributor

non commented Sep 12, 2016

@adelbertc in the worst-case you can make the test platform-specific using if (Platform.isJvm) .... This might be a good candidate for that.

I know ScalaTest supports a style of asynchronous testing that works with futures in JS, so you could also look into that.

@adelbertc
Copy link
Contributor Author

@non I looked into the async testing support in ScalaTest but it seems like due to how our tests are constructed it's not really compatible? My understanding is the new async stuff lets you give ScalaTest a Future[Assertion] instead of just an Assertion, but our laws use Eq which want Boolean ?

@non
Copy link
Contributor

non commented Sep 13, 2016

Looks like the build failed because some of our .tut files need updating.

@adelbertc Understood. It seems like it would be a big undertaking to try to change our test code to be able to take advantage of that feature. What you have here seems good for now.

@codecov-io
Copy link

codecov-io commented Sep 13, 2016

Current coverage is 91.72% (diff: 100%)

Merging #1370 into master will increase coverage by <.01%

@@             master      #1370   diff @@
==========================================
  Files           239        238     -1   
  Lines          3611       3600    -11   
  Methods        3484       3474    -10   
  Messages          0          0          
  Branches        126        125     -1   
==========================================
- Hits           3312       3302    -10   
+ Misses          299        298     -1   
  Partials          0          0          

Powered by Codecov. Last update 155f7f5...5a5ebb9

@johnynek
Copy link
Contributor

Of course, I'm +1. I think asking for stack safety (given it seems always achievable) is fine.

I do know of a Monad that was not made stack safe (yet?) Enumeratee, I think it was in iteratee-io (@travisbrown). I have not looked too hard at making it stack safe.

One issue is that the worst case may require trampolines and some library authors might not like that. I wonder if we could devise a trampoline-like approach that only impacts tailRecM and does not hurt the performance of flatMap.

@adelbertc
Copy link
Contributor Author

@johnynek The more I think of it the more convinced I am tailRecM should be enforced and monadic recursion in Cats should be stack safe (assuming callers implement lawful instances). I think I am OK worst case having users go through a trampoline.

I am curious about that data type you talked about in @travisbrown 's iteratee lib though.

@kailuowang @non Do I have a 👍 from either of you? :D

@travisbrown
Copy link
Contributor

@johnynek @adelbertc io.iteratee.Enumerator has a monad instance but the tailRecM is not (currently) stack-safe. The approach that Cats uses in e.g. the instance for Vector should work, but it was non-trivial and recursive binding for enumerators isn't a use case I've ever run into, so I passed on it in the 0.6 release.

Copy link
Contributor

@kailuowang kailuowang left a comment

Choose a reason for hiding this comment

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

This comment mentioning the defaultTailRecM impl should be removed
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/FlatMap.scala#L94-L108

@kailuowang
Copy link
Contributor

👍

@adelbertc adelbertc merged commit 77912ce into typelevel:master Sep 19, 2016
@stew stew removed the in progress label Sep 19, 2016
@kailuowang kailuowang mentioned this pull request Oct 19, 2016
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make stack safety law part of FlatMapRec as opposed to ad-hoc checks
8 participants