snoyberg / classy-prelude

A typeclass-based Prelude.
108 stars 15 forks source link

Resources for understanding how to use classy-prelude idiomatically #88

Open AKurilin opened 9 years ago

AKurilin commented 9 years ago

I'm trying to figure out if there are any recent online resources out there for understanding how to make the most out of classy-prelude and how one should be using it idiomatically as of late 2014 .

gregwebs commented 9 years ago

There are a couple of links in the README.md, are those still super relevant or has any of that been superceded?

They should be relevant, let us know if they are not. One problem is probably that we are assuming previous usage of Functor/Foldable/Traversable. It is easy to find documentation for those. Another problem may be a lack of documentation for IsSequence and Textual.

If you give us more specifics about the new user perspective that would be very helpful. It seems like you mostly just want a thorough overview though, which I think is sorely needed.

Any repositories out there that might demonstrate great use of classy-prelude?

classy-prelude is for application authors, not libraries, so that may be hard to find.

AKurilin commented 9 years ago

They should be relevant, let us know if they are not.

Okie dokie.

If you give us more specifics about the new user perspective that would be very helpful. It seems like you mostly just want a thorough overview though, which I think is sorely needed.

Basically this. As a beginner who has only ever used regular Prelude, I don't quite know what I'm supposed to improve on just by looking at classy-prelude. I think there's room for a guide that'd say something like: instead of using x, use y instead for reason z. e.g. use Foldable instances instead of Data.List functions directly because that way you can reuse the same function everywhere etc etc.

snoyberg commented 9 years ago

I agree that some kind of an introduction would be great. @gregwebs were you planning on writing that? If not, I'll likely take a crack at that in the next few days, at the very least it would be good for me to have for the rest of my team to be able to understand my code ;)

gregwebs commented 9 years ago

I will write something tomorrow. The open question is whether it should be in the Yesod scaffolding (in which case it should be in the book also). My feeling is that beginners are not ready for MinLen. Perhaps the scaffolding could have classy-prelude with MinLen taken out. I am not sure if that means partial functions are put back in, I think that means Safe versions are put in.

AKurilin commented 9 years ago

Any way MinLen could be explained well enough that beginners might understand it as well? I understand that it bloats the amount of stuff you need to learn to be able to start using it.

gregwebs commented 9 years ago

@AKurilin please give us some feedback on the mono-traversable README and then I can write something up for classy-prelude that references that.

AKurilin commented 9 years ago

Took me a couple of reads to understand it, but I'm also reasonably new. The MinLen is (to me) crazy type gymnastics, but it's cool that it exists. I think the description overall is pretty good! I'd say that if I could make a wish, that'd be to have "best practices" delineated somewhere, for either classy-prelude or mono-traversable or both.

Sent a PR with a couple of small text fixes.

gregwebs commented 9 years ago

Is there a package out there that might implement IsSequence for containers such as NonEmpty?

That is SemiSequence. The rest of the methods in IsSequence will require you to do the toList conversion first. But this is because those methods are going to reduce you down to a List anyways. Although that is not actually the case for all of the metods. We could try and fix that to make some more available to NonEmpty. I do still end up importing qualified Data.List.NonEmpty as NE in a few places.

gregwebs commented 9 years ago

As for best practices, I think it is just: import ClassyPrelude. The main problem seems to be understanding classy-prelude (which we are addressing) and working with some edge cases, such as your question about NonEmpty (keep them coming). But there is mostly just one way to use ClassyPrelude, the exception probably being some things around the partial functions that are made total.

AKurilin commented 9 years ago

Do you guys have advice on how to go about using text types with classy-prelude? e.g. I want to use error, but that will require String, and often I will have Text or ByteString that I want to pass to it. Typically I'd find the right pack/unpack version and normalize everything to a String, is there a better way of handling all these various permutations of conversions in classy-prelude?

I also looked for something like terror (since you already have tshow) (awesome function name) to see if that'd be an option.

gregwebs commented 9 years ago

do you want to pile onto this issue? https://github.com/snoyberg/classy-prelude/issues/83

I like terror also: I did that in Shelly.

I think we just need a pull request for this stuff now.

AKurilin commented 9 years ago

I'm honestly don't know enough about the overall ecosystem to say whether it should default to Text or not. Is it worthwhile to have a version of error that can work with anything that is an IsString maybe? I can see scenarios where you want to throw an error with Text/Bytestring/String in it and save yourself a conversion.

Btw, did you guys ever plan on moving the $(err) helpers from File Location or is that too opinionated?

snoyberg commented 9 years ago

In a solid +1 on terror. For converting to String, I'm only aware of two cases. For truly textlike things, unpack should be sufficient. For binary data, you'll need to use something like decodeUtf8 first.

gregwebs commented 9 years ago

If you don't accept a concrete type then you end up requiring a type signature, so I think it is usually best to just take Text or ByteString or in this cases to add terror.

When using monad-logger you can already use $logError to get the line number, but looking into adding some things from file-location is a good idea.

AKurilin commented 9 years ago

$logError doesn't crash the process though, right? I thought the point of $err was to throw an exception + have a source file location, right?

gregwebs commented 9 years ago

yes, that is correct and a good reason to look at adding $err.

AKurilin commented 9 years ago

I was hoping you could clarify a point I'm confused about with classy-prelude: what is your recommendation regarding dealing with Data.List when I want to enfore non-emptiness?

Is the best practice to use Data.List.NonEmpty in place of lists and then convert them with toMinList to a NonEmpty whenever I want to use Foldable/Traversable on them?

Basically, given the current state of exports done in the latest version of the ClassyPrelude module, what is the recommendation?

gregwebs commented 9 years ago

It is the same choice as whether to use a concrete List or a Functor/Foldable/Traversable structure.

NonEmpty is concrete, and concrete types are be easier to work with when that is all you need. The odd thing is probably just that there is a NonEmpty counterpart to a List and there is no other counterpart for other structures. So theoretically it is simpler to not bother with NonEmpty. But Haskell is very List biased (or was before 7.10!).

AKurilin commented 9 years ago

What is the more abstract alternative to NonEmpty if I still want something list-like?

gregwebs commented 9 years ago

NonNull [a]

AKurilin commented 9 years ago

Awesome, will try that!