Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upList.map2 unexpected behavior #355
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jvoigtlaender
Aug 17, 2015
Contributor
As to why:
- The
Applicativeinstance for standard lists in Haskell is this. - But there's also an
Applicativeinstance for so-calledZipLists, here. - Of the two, Elm chooses the
ZipListversion (because, I think, it's the one that is analogous to theApplicativeinstance forSignal).
Continuing your example, in Haskell you would have:
ZipList [5,7] = (+) <$> ZipList [1,2,3] <*> ZipList [4,5]|
As to why:
Continuing your example, in Haskell you would have: ZipList [5,7] = (+) <$> ZipList [1,2,3] <*> ZipList [4,5] |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Aug 17, 2015
Member
I think this library does what you want.
The idea is that the "exploring all possibilities" version of things is way less common in practice. I have still not used lists that way in a real life Haskell program after like 5+ years.
|
I think this library does what you want. The idea is that the "exploring all possibilities" version of things is way less common in practice. I have still not used lists that way in a real life Haskell program after like 5+ years. |
evancz
closed this
Aug 17, 2015
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Fresheyeball
Aug 17, 2015
Hmm, I thought the definition of Lists as a Applicative Functor needed to consistent with List as a Monad.
Doesn't this break that? It may be more practical in practice, but it feels unsound (I'm not actually a math guy). NDet also doesn't seem like the appropriate place for this, as the result should be deterministic. Believe it or not, I use this functionality somewhat regularly. Maybe it should be added to List.Extra?
Fresheyeball
commented
Aug 17, 2015
|
Hmm, I thought the definition of Lists as a Applicative Functor needed to consistent with List as a Monad. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Aug 17, 2015
Member
Maybe talk to the List.Extra folks. There are some discussions on the list about how the applicative laws are not followed exactly with how it works here. I think both sides of this are explained there if you can find it.
Not looking to change this really. The fact that something can be seen as an Applicative Functor does not necessarily mean that's the best API.
|
Maybe talk to the Not looking to change this really. The fact that something can be seen as an Applicative Functor does not necessarily mean that's the best API. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Fresheyeball
Aug 18, 2015
Fair enough. I submitted a PR to List.Exta. We will see what they say. Overall I've enjoyed how elm tends to fall on the side of good api in good api vs math when those are in conflict (Error over Either ect). But I feel like the true math thingies still need a home.
Fresheyeball
commented
Aug 18, 2015
|
Fair enough. I submitted a PR to List.Exta. We will see what they say. Overall I've enjoyed how elm tends to fall on the side of good api in good api vs math when those are in conflict ( |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jvoigtlaender
Aug 18, 2015
Contributor
@Fresheyeball, saying "Lists as a Applicative Functor needed to consistent with List as a Monad" isn't very relevant when there is no Monad instance for Lists (in Elm). Also, as observed already in the original "Applicative Functors" paper, a type constructor (like List) can have more than one useful Applicative Functor instance. I think they even use the above example with the two different ways of making lists Applicative in Haskell:
[5,6,6,7,7,8] = (+) <$> [1,2,3] <*> [4,5]
ZipList [5,7] = (+) <$> ZipList [1,2,3] <*> ZipList [4,5]Only one of the two (the first) has a corresponding Monad instance. Because none can exist for the second. That doesn't mean the second one is not a useful Applicative instance. There is also nothing unsound about it. It satisfies all the laws expected of Applicatives. (I don't understand Evan's comment about "how the applicative laws are not followed exactly with how it works here". I think they are followed just fine.)
About NDet and determinism, yes, of course the resulting list is a deterministic value. But it models nondetderminism. After all, the "List as a Monad" you mention is typically called the nondeterminism monad.
|
@Fresheyeball, saying "Lists as a Applicative Functor needed to consistent with List as a Monad" isn't very relevant when there is no Monad instance for Lists (in Elm). Also, as observed already in the original "Applicative Functors" paper, a type constructor (like [5,6,6,7,7,8] = (+) <$> [1,2,3] <*> [4,5]
ZipList [5,7] = (+) <$> ZipList [1,2,3] <*> ZipList [4,5]Only one of the two (the first) has a corresponding Monad instance. Because none can exist for the second. That doesn't mean the second one is not a useful Applicative instance. There is also nothing unsound about it. It satisfies all the laws expected of Applicatives. (I don't understand Evan's comment about "how the applicative laws are not followed exactly with how it works here". I think they are followed just fine.) About |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Fresheyeball
Aug 18, 2015
@jvoigtlaender fascinating! That was all news to me, like I said, I'm not a math guy. So... it sounds like both of the examples you provided are useful and valid Applicative instances, and I was more just accustomed to the first one because I think of lists as Monads and mentally work backward to Applicative.
If this was a system with type-classes where there is an Applicative class and a Monad class, I expect them to align, making the ZipList version a newtype. But this is Elm, and it seems fair that the ZipList version is more useful in practice. It all seems good to me. @circuithub already merged my PR with the other instance.
If you are willing to humor me. Why is the List Monad called the nondeterminism monad when the values produced are deterministic?
Fresheyeball
commented
Aug 18, 2015
|
@jvoigtlaender fascinating! That was all news to me, like I said, I'm not a math guy. So... it sounds like both of the examples you provided are useful and valid Applicative instances, and I was more just accustomed to the first one because I think of lists as Monads and mentally work backward to Applicative. If this was a system with type-classes where there is an Applicative class and a Monad class, I expect them to align, making the ZipList version a newtype. But this is Elm, and it seems fair that the ZipList version is more useful in practice. It all seems good to me. @circuithub already merged my PR with the other instance. If you are willing to humor me. Why is the List Monad called the nondeterminism monad when the values produced are deterministic? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jvoigtlaender
Aug 18, 2015
Contributor
About "list monad = nondeterminism monad" (in classic math papers, it would probably be "set monad = nondeterminism monad", but most functional programmers make do with lists): All the answers here and here seem good to me. Also one of Wadler's first monad papers (for functional programmers) contains such a discussion. (It discusses a series of extensions of a base interpreter for a simple language. When it comes to realizing a nondeterministic language feature, the natural monad to choose is the list monad.) A precursor to this, before the general concept of monads was introduced into FP, was his paper "How to Replace Failure by a List of Successes" (easy to find online), which uses lists for modelling backtracking, but uses just list comprehensions instead of a monadic API.
|
About "list monad = nondeterminism monad" (in classic math papers, it would probably be "set monad = nondeterminism monad", but most functional programmers make do with lists): All the answers here and here seem good to me. Also one of Wadler's first monad papers (for functional programmers) contains such a discussion. (It discusses a series of extensions of a base interpreter for a simple language. When it comes to realizing a nondeterministic language feature, the natural monad to choose is the list monad.) A precursor to this, before the general concept of monads was introduced into FP, was his paper "How to Replace Failure by a List of Successes" (easy to find online), which uses lists for modelling backtracking, but uses just list comprehensions instead of a monadic API. |
Fresheyeball commentedAug 17, 2015
Maybe this is intentional but:
obviously
[5,6,6,7,7,8] /= [5,7], why? Is there a utility function to provide the traditional lift behavior?