haskell-numerics / hmatrix

Linear algebra and numerical computation
381 stars 104 forks source link

Request to make `R n` a Functor. #252

Closed capn-freako closed 6 years ago

capn-freako commented 6 years ago

Hi,

Having your data type, R n, not be a Functor is causing us some pain, and we're wondering: is it possible to make it a Functor?

Thanks!

idontgetoutmuch commented 6 years ago

Do you mean the one in Numeric.LinearAlgebra.Static?

We have

Prelude Numeric.LinearAlgebra.Static> :k R
R :: GHC.Types.Nat -> *

But

class Functor (f :: * -> *) where

So R has the wrong kind to be a functor?

capn-freako commented 6 years ago

Yes, that’s the one. And, yes, you have identified the problem exactly correctly.

Thanks, -db

On Feb 22, 2018, at 3:17 PM, idontgetoutmuch notifications@github.com wrote:

Do you mean the one in Numeric.LinearAlgebra.Static?

We have

Prelude Numeric.LinearAlgebra.Static> :k R R :: GHC.Types.Nat -> * But

class Functor (f :: -> ) where So R has the wrong kind to be a functor?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/albertoruiz/hmatrix/issues/252#issuecomment-367856013, or mute the thread https://github.com/notifications/unsubscribe-auth/AA_7ml1Mlr0JVAJPvX1N_9RnzzT7U1rwks5tXfV1gaJpZM4SQH5k.

mstksg commented 6 years ago

What is the main point of pain for R not being a Functor for you?

capn-freako commented 6 years ago

I’m attempting to integrate use of another library with my use of hmatrix. However, that library demands that my “vector” data type be a Functor. -db

On Feb 22, 2018, at 6:20 PM, Justin Le notifications@github.com wrote:

What is the main point of pain for R not being a Functor for you?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/albertoruiz/hmatrix/issues/252#issuecomment-367889452, or mute the thread https://github.com/notifications/unsubscribe-auth/AA_7msHEUU54uzIMWad0X3BTUzrM2l84ks5tXiBtgaJpZM4SQH5k.

mstksg commented 6 years ago

What sort of operations would you be expecting?

It is easy to make R n a functor using a type like Const:

type RFunctor n = Const (R n)

So fmap, etc. are defined on it, and things would have the right kind.

fmap :: (a -> b) -> RFunctor n a -> RFunctor n b

Note however that it isn't possible to have a Functor instance where fmap would map over the contents, because R can only store storable items. So there isn't any way to have fmap work over the contents, because fmap is meant to be polymorphic for all as and bs.

This is similar to the reason why Set (from http://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Set.html) cannot be a Functor -- its mapping function requires that the items all be instances of Ord, but Functor is too generic for that. See the discussion at https://www.reddit.com/r/haskell/comments/2090x3/ask_rhaskell_why_is_there_no_functor_instance_for/ for further elaboration as to why it isn't possible for Set to have a Functor instance that maps over its contents, and why R n can't have a Functor instance that maps over its contents. (Set requires Ord for its contents, and Vector requires Storable), even if the kinds matched.

Note that the Storable constraint on the contents of Vector are inherent to the nature of the hmatrix library: it's basically a wrapper over C libraries, and the Storable constraint is necessary for working with the FFI.

So:

  1. If your library just wants something to fit the shape of Functor and have an instance, and you don't need fmap to map over the contents, type RFunctor n = Const (R n) will do fine to appease your library and make the kinds match up.
  2. If you want some sort of container where the Functor instance maps over the contents, it isn't possible due to the nature of hmatrix being a wrapper over C libraries. However, if this is what you want, consider alternate vector libraries like http://hackage.haskell.org/package/vector-sized.
capn-freako commented 6 years ago

Thanks, Justin!

The constraints imposed by the use of Storable vectors hadn’t occurred to me.

Your explanation, as well as proposed work around for some cases, seems sufficient to me. I’ll wait 24 hours, to allow the others watching to comment, and then close this issue.

Thanks, -db

On Feb 23, 2018, at 3:03 PM, Justin Le notifications@github.com wrote:

What sort of operations would you be expecting?

It is easy to make R n a functor using a type like Const:

type RFunctor n = Const (R n) So fmap, etc. are defined on it, and things would have the right kind.

fmap :: (a -> b) -> RFunctor n a -> RFunctor n b Note however that it isn't possible to have a Functor instance where fmap would map over the contents, because R can only store storable items. So there isn't any way to have fmap work over the contents, because fmap is meant to be polymorphic for all as and bs.

This is similar to the reason why Set (from http://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Set.html http://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Set.html) cannot be a Functor -- its mapping function requires that the items all be instances of Ord, but Functor is too generic for that. See the discussion at https://www.reddit.com/r/haskell/comments/2090x3/ask_rhaskell_why_is_there_no_functor_instance_for/ https://www.reddit.com/r/haskell/comments/2090x3/ask_rhaskell_why_is_there_no_functor_instance_for/ for further elaboration as to why it isn't possible for Set to have a Functor instance that maps over its contents, and why R n can't have a Functor instance that maps over its contents. (Set requires Ord for its contents, and Vector requires Storable).

Note that the Storable constraint on the contents of Vector are inherent to the nature of the hmatrix library: it's basically a wrapper over C libraries, and the Storable constraint is necessary for working with the FFI.

So:

If your library just wants something to fit the shape of Functor and have an instance, and you don't need fmap to map over the contents, type RFunctor n = Const (R n) will do fine to appease your library and make the kinds match up. If you want some sort of container where the Functor instance maps over the contents, it isn't possible due to the nature of hmatrix being a wrapper over C libraries. However, if this is what you want, consider alternate vector libraries like http://hackage.haskell.org/package/vector-sized http://hackage.haskell.org/package/vector-sized. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/albertoruiz/hmatrix/issues/252#issuecomment-368163881, or mute the thread https://github.com/notifications/unsubscribe-auth/AA_7mqkmjLKFIdC4o8Zpnrbc3GOIx3Xhks5tX0PegaJpZM4SQH5k.

albertoruiz commented 6 years ago

Justin: excellent explanation!

Thanks!

idontgetoutmuch commented 6 years ago

I still don't understand the use case but do you want https://hackage.haskell.org/package/mono-traversable?

capn-freako commented 6 years ago

Thanks for the pointer. I’ll check it out. -db

On Feb 24, 2018, at 3:26 AM, idontgetoutmuch notifications@github.com wrote:

I still don't understand the use case but do you want https://hackage.haskell.org/package/mono-traversable https://hackage.haskell.org/package/mono-traversable?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/albertoruiz/hmatrix/issues/252#issuecomment-368221852, or mute the thread https://github.com/notifications/unsubscribe-auth/AA_7mluoGbmnvtj77OkgJwYBwk_pzeVNks5tX_H3gaJpZM4SQH5k.

capn-freako commented 6 years ago

Thanks to all, whom responded! Closing.