You'd generalise it to:
fmap . fmap :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
And then, would you do the same for Traversable, Foldable and Applicative?
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
Some of you might be familiar with (.:) = (.) . (.).
It has type :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.).(.) :: (Category cat) => cat c d -> (a -> cat b c) -> a -> cat b d
I know little about Category Theory, but throwing together some random words I collected over time that looks like... a "contravariant bind in the monad of endocategories", maybe? I just invented that and it's almost certainly meaningless gibberish, but knowing our community it might well be that there's a lib for that.
Also, why ish = f .: g == (f .) . g
not good enough?
So many questions, so much bikeshedding to do, so little time...
(Forgot reply all)
On 18/08/16 23:57, Mike Ledger wrote:
> IMO: I've never seen a compelling use of this; I think it decreases
> clarity, and barely shaves off any characters from equivalent "pointful"
> expressions.
I think it quite compelling. An example:
asSeconds :: Hour h -> Minute m -> Second s -> Second t
- -- | asSeconds take some 'TimeUnit's and convert them to 'Second's.
asSeconds h m s = MkSecond $ 3600 * timeVal h + 60 * timeVal m + timeVal s
hmsToDiffTime :: Hour h -> Minute m -> Second s -> DiffTime
- -- | 'hmsToDiffTime' converts time of day in hours, minutes and seconds to the
- -- time from midnight as a 'DiffTime'.
hmsToDiffTime = (secondsToDiffTime . timeVal) .:. asSeconds
As for putting it in base -- meh. I use the composition package, or
define it myself. So I agree with Oleg; -1.
- --
Alexander
alex...@plaimi.net
https://secure.plaimi.net/~alexander
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQIcBAEBCgAGBQJXtwTXAAoJENQqWdRUGk8BP/UQAIcKzqVRhkVs0qtFDneTpSIi
jLPPXMELbMnQe/ZQH2c5SaVM4+eDJIky33FEzrh9FWMeDftz1QFrsC+pPq+5/Esw
U3h1HJrAJKl+zZ/bC1GQj9ObWKNROj3jEEt9pyNBcoHpxVnCohD3Y6Gx2LknE7m0
hnFlO0rCZZamk+pSeSlmLkkDM/MNxTx/FQcuZT0omxZtvzrz4cN7a069Gx35C+vr
RK6NpiD5NUqTvMCL0zeI2yRpg2GV2PQcwV0CEWjLCsJYMcoeiF8+prSBdwzatgjH
7k1bHUdGwvcRzB74dyxIOPyHBgIDUFzj7bcE+NT0V20WXaz/Jgl73zZaIG9XtW19
aJ+RzW+aBSLEh8+uERc+Al9NpM9dLR94mDWIK/MZWEmlFHo8+W/md27+OxvM5BOr
YCRpoQYeYDkepTAyRK2wRlszFXydDze8K6PMAq4DUE7xtUXofEbcodWA0quLxP4N
ro2A8E4kqnO6BVD7iN+qch8TxmEiVYpqZnAjNz8eSyQCdn9UORpcMLT8yQ963nml
17yKRjHYDwg/g8EC1UjqJ9KwVFRhqQwdk//IupRyZ/5PPkEChy8t/ZjmmGKfLy0H
CfhpRiNi0ozR+bYpUJcOdNM0ckCzgq5++9+M643RGjNWvD4fKDI8idNNn9eLlcom
kaABFBC5Gbx2O6/rgpHc
=X/Rb
-----END PGP SIGNATURE-----
I didn't even know about the composition package. I just wanted it to be readily available to everyone.
A quick look, `composition` seems really nice and is probably more aligned with Haskell ecosystem's philosophy of keeping base to what is only stricly needed by GHC.
These were some valuable feedback. I think I got my answer and we can let the thread die (:
Much appreciated,
Alex
Hi,
Am Freitag, den 19.08.2016, 11:16 -0700 schrieb Theodore Lief Gannon:
> Well... there's that rather worrisome introductory paragraph of the
> Data.Composition docs, though:
>
> "This module is for convenience and demonstrative purposes more than
> it is for providing actual value. I do not recommend that you rely on
> this module for performance-sensitive code. Because this module is
> not based on Prelude's (.), some chances at optimization might be
> missed by your compiler."
I wonder if that is really something to worry about. Prelude’s (.) is
not special in any way:
The INLINE pragma and the definition with the right arity could be used
in Data.Composition as well, and it would yield the same results.
> Any RULEs involving Prelude’s (.) would need to be copied as well.
There aren't any, and if there are any then they're almost certainly
broken. The INLINE pragma on (.) isn't marked with a simplifier phase,
so it will be inlined almost immediately when optimization begins, as
long as it has at least two arguments. There is no time for rules
involving it to take effect. Rewrite rules end up working with the
inlined version. For example, Data.Sequence has a rule saying
forall f g xs . fmapSeq f (fmapSeq g xs) = fmapSeq (f . g) xs
So if you write
fmap f . fmap g
for sequences, this will specialize to
fmapSeq f . fmapSeq g
and inline to
\xs -> fmapSeq f (fmapSeq g xs)
at which point the rewrite rule will fire, changing it to
\xs -> fmapSeq (f . g) xs
This, in turn, will inline as well, to
\xs -> fmapSeq (\x -> f (g x)) xs
Yes and no. Prelude's (.) is not special in that GHC doesn't identify
it as something that must be treated differently from what's expected
from the definition (as opposed to, say, ($)). However, (.) is
inherently a special case because of performance issues about
closures. For example, whether we define:
(.) f g = \x -> f (g x)
vs:
(.) f g x = f (g x)
has ramifications, though it's fairly easy to guess which one of those
two will be most performant. However, it's much less clear which of
the following definitions will be the most performant:
(.:) = (.) . (.)
(.:) f g = (f .) . g
(.:) f g = \x y -> f (g x y)
For the version implemented in pointless-fun:Data.Function.Pointless,
I actually did some benchmarking to determine which was fastest. It is
(a) faster by a surprisingly large margin, and (b) not the one I
expected to be the fastest. I haven't run those benchmarks on the
latest versions of GHC, but that just underscores the point. Because
the performance difference is significant and unexpected, having a
single blessed (and maintained!) definition would be beneficial to
anyone who actually uses this function in production code— whether
that blessed definition is in base or some other library everyone has
and knows about.
--
Live well,
~wren
Are these not synonyms? What is the meaning of
fargs var = expr
if not
fargs = \var -> expr
?
On Mon, Aug 22, 2016 at 10:23:07PM -0700, wren romano wrote:(.) f g = \x -> f (g x)
vs:
(.) f g x = f (g x)
has ramifications, though it's fairly easy to guess which one of those
two will be most performant.
Are these not synonyms? What is the meaning of
fargs var = expr
if not
fargs = \var -> expr
?
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
module Foo where
comp1 f g x = f (g x)
comp2 f g = \x -> f (g x)
% ghc -O0 -dsuppress-all -fforce-recomp -no-link -ddump-prep test.hs
[1 of 1] Compiling Foo ( test.hs, test.o )
==================== CorePrep ====================
Result size of CorePrep = {terms: 24, types: 36, coercions: 0}
comp2
comp2 =
\ @ t_aeU @ t1_aeV @ t2_aeW f_sfz g_sfy x_sfx ->
let {
sat_sfI
sat_sfI = g_sfy x_sfx } in
f_sfz sat_sfI
comp1
comp1 =
\ @ t_af5 @ t1_af6 @ t2_af7 f_sfG g_sfF x_sfE ->
let {
sat_sfJ
sat_sfJ = g_sfF x_sfE } in
f_sfG sat_sfJ
(the same holds for -O2, if you compile them separately)
On Tue, Aug 23, 2016 at 05:19:38PM +1000, Ben wrote:
> At the semantic level of "does my program compute correct results" they're
> identical. At the operational level of "how fast does my program run"
> they're different.
>
>
> On August 23, 2016 5:09:19 PM GMT+10:00, Tom Ellis <tom-lists-has...@jaguarpaw.co.uk> wrote:
> >On Mon, Aug 22, 2016 at 10:23:07PM -0700, wren romano wrote:
> >> (.) f g = \x -> f (g x)
> >>
> >> vs:
> >>
> >> (.) f g x = f (g x)
> >>
> >> has ramifications, though it's fairly easy to guess which one of
> >those
> >> two will be most performant.
> >
> >Are these not synonyms? What is the meaning of
> >
> > fargs var = expr
> >
> >if not
> >
> > fargs = \var -> expr
> >
> >?
_______________________________________________
On the other hand, it is not very common to write
> (.) f g x
which is why (.) is defined in such a way.
Matt
On Tue, Aug 23, 2016 at 8:33 AM, Tom Ellis
GHC will only inline the function if it is fully applied, where “fully
applied” means applied to as many arguments as appear (syntactically) on
the LHS of the function definition
That this is a good heuristic is *extremely* counterintuitive to me. I
would have supposed that being more explicit, for example
{-# INLINE (.) f g #-}
to inline on all static applications of at least two arguments would have
been a much clearer way to communicate this message.
What's the rationale behind the current behaviour?
Tom
On Tue, Aug 23, 2016 at 09:56:25AM +0100, Matthew Pickering wrote:
> I think the point which no-one has articulated yet is that the
> source-level arity of (.) affects whether GHC will decide to inline it.
>
> Only fully saturated applications are inlined
[...]
Suddenly the eta reduce hlint warning becomes much more important.
Alan
*Very* interesting. Here is the key section of the GHC users guide:
GHC will only inline the function if it is fully applied, where “fully
applied” means applied to as many arguments as appear (syntactically) on
the LHS of the function definition
That this is a good heuristic is *extremely* counterintuitive to me. I
would have supposed that being more explicit, for example
{-# INLINE (.) f g #-}
to inline on all static applications of at least two arguments would have
been a much clearer way to communicate this message.
What's the rationale behind the current behaviour?
Tom
On Tue, Aug 23, 2016 at 09:56:25AM +0100, Matthew Pickering wrote:
> I think the point which no-one has articulated yet is that the
> source-level arity of (.) affects whether GHC will decide to inline it.
>
> Only fully saturated applications are inlined
[...]
>
> On Tue, Aug 23, 2016 at 8:33 AM, Tom Ellis
And also sometimes wrong. I don't really understand why, but sometimes eta *expansion* is important when working around RULES.
Suddenly the eta reduce hlint warning becomes much more important.
Alan