-
-
Notifications
You must be signed in to change notification settings - Fork 35
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
Multiarity fmap is no longer fmap #12
Comments
Thank you for the patience and a very detailed description. It would be very helpful if you could translate the problem to clojure code that demonstrate the issue. That would help in deciding how to handle it. |
The exact problem should be invariant to the language used to write it. The specific Clojure code is in the definition of the Functor protocol (defprotocol Functor
(fmap [fv g] [fv g fvs])) should be, I believe (defprotocol Functor
(fmap [fv g])) as the variadic |
Can you provide a demonstration case where that is a problem? |
It won't cause any problems, just reduce the orthogonality of your interface. Anyone implementing it will need to also design the data Void = Void Void
data Foo x = Foo { foo :: Void }
instance Applicative Foo where -- this cannot exist, else
foo (pure ()) :: Void -- we could construct Void, which is invalid As a larger example, it's often valid to construct data Const b a = Const { getConst :: b }
instance Functor (Const b) where fmap (Const b) = Const b
instance Monoid b => Applicative (Const b) where
pure _ = Const mempty
Const b1 <*> Const b2 = Const (mappend b1 b2) and these are always Really, the sum of my issue is just that it's not valid to say something is a functor and ask for a variadic |
Since the goal is not 100% compatibility with Haskell, but a familiarity and usefulness for Clojure developers, I keep the variadic fmap. Honestly, even Haskell have its confusing points when it comes to CT, at least to me (I am not an CT expert nor a mathematician, BTW). If there is a serious practical programming problem, I'll reconsider this, otherwise I think compatibility with Clojure is more important than compatibility with Haskell. |
My concern is not so much that this should be compatible with Haskell either. I'm also not invested in saying whether or not this produces familiarity or usefulness for Clojure developers. In totality, the problem is that whether or not variadic |
Then, as a secondary note, variadic |
While reading the Fluokitten documentation I noticed that it's often touted as an advantage of implementing these concepts in Haskell that
fmap
is able to variadic. Later, it's pointed out Haskell requires using(<*>)
orap
to achieve this effect.The problem is that variadic
fmap
just isn'tfmap
—it's a stronger requirement than just being a Functor. In particular, it imbues a kind of sequencing on your "Functor" which is above the call of duty for just having a Functor—you're opening up each of the boxes in sequence, calling the combining function, then closing them back. A normal functor should disallow that.One place this distinction shows up is that it prevents you from extracting the commonalities between various applicative instances of Lists/vectors. The applicative instance of vector in Fluokitten is the "Cartesian applicative"
But there's also a law-abiding applicative instance for Lists/vectors of any fixed length. Often this is implemented with infinite lists in Haskell
This is all well and good—these are distinct types. However, it's important to note that they both have identical Functor instances so long as
fmap
is not variadic.In fact, in Haskell we have the guarantee that there is exactly one non-pathological function with the type
and satisfying
fmap id = id
. That's the power of the Functor laws.Obviously, it's a design choice in Fluokitten to include variadic
fmap
or not, but it's a patent inaccuracy in the documentation to call an interfaceFunctor
if it provides a variadicfmap
.The text was updated successfully, but these errors were encountered: