Someone who knows #Haskell and ML: is there a writeup somewhere explaining how first-class modules (a la ML) can do similar things to Haskell type classes? I'm finding it hard to figure that out.
To give a more concrete case: suppose I wanted to write something like Control.Applicative, which provides an 'interface' Applicative with some methods, as well as functions that work for any Applicative. How would I do this with ML-style first-class modules?
@koz I would like to see such a comparison post too. In the meantime I found this stackoverflow question which contains a way to do it using an ML functor: https://stackoverflow.com/questions/48989663/monads-and-sml-modules. The obvious downside is that you have to explicitly state which monad to use at some point.
Another lesser known difference is that I believe you can't instantiate an ML signature with a polymorphic type. For example you can't write an instance of that MAPPABLE signature for a type like Map k v. At least not such that it is still polymorphic over the key type k.
@DiazCarrete That slide seems to misrepresent effect systems. It is easy to replace just runInputConst:
runAllEffects (runInputDifferently program)
The runInputDifferently effect handles the Input Config effect and it leaves an unused Input Config in the list of effects. So the runInputConst config handler in runAllEffects will not be used.
@someodd Also note that the advice is about Stackage and not Stack. You can use Stackage snapshots with Cabal. E.g. you can create a cabal.project file with a line like this: import: https://www.stackage.org/lts-22.16/cabal.config. It still has a lot of rough edges, for example it is not possible to override specific constraints from the snapshots, but it is usable.
Is it just me or is this whole thing about „don’t do X if you don’t really know what you’re doing“ really counter productive? Many people live in fear of X now and don’t start thinking if X is an actual problem or learn what the problems are that could rise from X.
I see this very often in the #haskell ecosystem where the solution to doing X properly is often learnt in a few minutes investigation.
@mangoiv I know I've said that a few times. Two examples I can think of:
AllowAmbiguousTypes, GHC suggests this but you should probably just use Proxy arguments instead.
Typeable, people coming from OOP languages often want a typeof function, but 99% of the time there is a better way to structure your programs using simple ADTs.
I still think these are not learnt in a few minutes. Even if that was the case, the most important thing you should learn is that you shouldn't use them very often.
@someodd What do you mean by "access"? GHC versions and base versions are tightly connected. GHC 9.0.2 is tied to base 4.15.1.0 (source). There is no way (yet) to change the base version used by GHC.
what would interest me is; how do you actually transfer imperative datastructures to functional ones; I have made the experience, that there are some mutable datastructures that are hard to find replacements for and one of them I once got so stuck on that I gave up finding an alternative for.
If you wanna riddle yourself, then here are the requirements: random access in O(1), including updatescons and snoc in O(1)
The imperative version of that datastructure is a simple mutable doubly list; random access is done by storing the pointers to the places you want to access and then just mutating the parts of the list in place; snoc and cons are just inserting a new element.
@mangoiv RE: "random access is done by storing the pointers to the places you want to access", that's not what I would consider random access, because if you want to be able to access any place in the list then you'd need to store all those pointers in an array and then you run into problems when you want to cons and uncons things in that array. So your proposed mutable solution only gives you random access for a select group of pointers, which cannot be changed in constant time.
I believe it is possible to generalise immutable fingertrees to have an arbitrary amount of "fingers" instead of just the one at the beginning and the one at the end of the sequence. That data structure would give you the same operations.
@DiazCarrete I don't think I'd want to change the string type that often, but being able to make it be a specific type instead of having it be overloaded would be nice.
I attempted to recreate it in #haskell, but we don't really have a library on the same level of abstraction. wai is too abstract and network is not abstract enough.