strictly speaking you only have instances where instances have been defined but for that to happen you have to be able to do so obeying the relevant laws
After learning a bit of Haskell, I think the reason Haskell is hard to learn isn't so much because of its complexity. Most sufficiently powerful languages have complex parts that are hard to wrap your head around (I'm thinking of metaclasses in Python, for example).
The difference is that in Python, the complex parts aren't things you have to deal with right away. You can be a perfectly capable Python programmer and never know anything about metaclasses. Whereas with Haskell, it seems that the complexity smacks you in the face almost right away and demands that you understand what a monad is before continuing.
Do you think that's a feature of the language itself, or is it more in the way Haskellers talk? Would a more "lies to children" approach be possible, where learners are told, "Do it this way and it works... don't worry about why just yet"?
@Nitrodon True, but I was already familiar with Lisp and Prolog when I first tried to learn Haskell. It's possible the static typing gave me some problems, but I don't think I had much trouble with (basic) functional programming concepts.
@Nitrodon For me it's two things: ease of use, and flexibility.
Ease of use, because I don't have to stop and think about what type I want this variable to be; I can just write the code, and if it doesn't work for the data I need to pass to it, it'll raise a TypeError and I'll fix it then. It speeds up the process of throwing some code together to get a quick-and-dirty version that does what you need, and then you can make it more robust afterwards.
Flexibility, because I can write a function that accepts an integer OR a float OR a string (and if the argument is a string, converts it to a number). Having to define the parameter as one and only one type feels like a straitjacket sometimes.
The main thing I do like about static typing is that it allows for IDEs that do static code analysis to tell you what types you can pass to a given function. With Python, it might have a docstring that gives that information, but if not, I have to either 1) find some documentation online, 2) read the implementation of the function, or 3) use trial and error to find out what works.
I'm a pretty trial-and-error sort of programmer (e.g. I haven't used a debugger in over a decade--if something's puzzling me, I put extra print statements in my code, run it, and see what the output looks like), but it would be nice sometimes to see what types of arguments I can pass to a function right there in a tooltip.
It could become a problem for me if I were developing an application in Haskell, yeah. But I haven't gotten that far yet. (Actually, I think for a functional language, some ad-hoc variety of unit-testing would replace the "stick print statements everywhere" approach.)
Okay, I think I've figured out how >>=, =<<, and <*> work when composing functions. Is this accurate?
f >>= g = \x -> g (f x) x g takes 2 arguments, f takes 1
f =<< g = \x -> f (g x) x f takes 2 arguments, g takes 1
f <*> g = \x -> f x (g x) f takes 2 arguments, g takes 1
So is f >>= g identical to g =<< f, or in other words (=<<) = flip (>>=) ? Or is there some extra difference, maybe when working with monads other than functions?
I just read through this SO answer and I think it's a great explanation of monads and why functions are monads too. I'm guessing it doesn't have many upvotes because it's a recent answer to an old question.
@Nitrodon Please don't put those two on the same level, they're very different languages. Javascript has clean syntax and sensible builtins, slightly cursed types, and it's cross-platform and pretty powerful. PHP, well...