Hi list,
Is there a syntax in Haskell for partial application that would be something like this the following ? f a b c d = a +b+ c+ d g = f _ 1 2 3 or the only way to do it is like below ? g = (\x -> f x 1 2 3) Also, hlint complains about top-level functions without type even if they are not exported out of the corresponding module. Is is really bad style not put type signatures in all top-level functions ? I really like the fact that haskell takes care of the type signatures for me. best, Miguel http://www.friendlyvirus.org/miguelnegrao/ |
On Mon, Dec 03, 2012 at 12:28:08PM +0000, Miguel Negrao wrote:
> Hi list, > > Is there a syntax in Haskell for partial application that would be something like this the following ? > > f a b c d = a +b+ c+ d > > g = f _ 1 2 3 > > or the only way to do it is like below ? > > g = (\x -> f x 1 2 3) Yes, a lambda is the only way to do it. > Also, hlint complains about top-level functions without type even > if they are not exported out of the corresponding module. Is is > really bad style not put type signatures in all top-level functions > ? I really like the fact that haskell takes care of the type > signatures for me. Yes, it is bad style. Let me give you two reasons why I always encourage putting type signatures on all top-level functions. Whether they are exported or not really makes no difference. 1. Writing the type signature for a function *first*, before implementing it, really helps a LOT in clarifying things in your own mind. If you cannot write down the intended type of a function then you do not understand what it is supposed to do. If you do not understand what it is supposed to do then how do you expect to be able to implement it? 2. Suppose you make a mistake when implementing a function. If you don't give a type signature, it's possible that GHC will infer some type for it anyway (but not the type you intended!). Now you will not get an error until further down the line when you use that function somewhere else. And what's more, the error will not tell you anything about the real problem. It will just say "X does not match Y on line 297" and you will have to do a lot of work to figure out that the real problem is that you messed up in implementing function foo on line 43. But if you had put a type signature on foo in the first place, you would have gotten an error immediately. -Brent |
On Mon, Dec 03, 2012 at 03:20:41PM +0000, Miguel Negrao wrote:
> > A 03/12/2012, ?s 12:53, Brent Yorgey escreveu: > >> Is there a syntax in Haskell for partial application that would be something like this the following ? > >> > >> f a b c d = a +b+ c+ d > >> > >> g = f _ 1 2 3 > > Yes, a lambda is the only way to do it. > > Given how compact haskell?s syntax can be, is there a reason why implementing such placeholders is not a good idea for haskell ? Yes: it would introduce horrible ambiguity. Consider (f (g _ 1 2)) Does it mean (f (\x -> g x 1 2)) or (\x -> f (g x 1 2)) ? I don't know of any good reason to prefer one over the other. Any rule you come up with is likely to have other weird corner cases you hadn't considered. As I understand it, Scala actually does have this feature, along with lots of confusing, ugly, ad-hoc rules to disambiguate situations like the above. > > 2. Suppose you make a mistake when implementing a function. If you > > don't give a type signature, it's possible that GHC will infer > > some type for it anyway (but not the type you intended!). Now > > you will not get an error until further down the line when you > > use that function somewhere else. And what's more, the error > > will not tell you anything about the real problem. It will just > > say "X does not match Y on line 297" and you will have to do a > > lot of work to figure out that the real problem is that you > > messed up in implementing function foo on line 43. But if you > > had put a type signature on foo in the first place, you would > > have gotten an error immediately. > Ok, I see your points. Number 2 does happen to me from time to > time, at which point I go back to the a point where the code worked > and introduce the type signatures with hlint, so yeah doing the > signatures would save me from having to do that. Sometimes I know > how to write a function but I don?t know how to write the type > signature because they are too complicated for my still reduced > knowledge of haskell, for instance, I don?t know when I need to use > the forall thing, which hlint sometimes introduces when it produces > the type signatures. Perhaps the problem might be that I should be > using less top-level functions and defining some of those functions > where they are used ? A lot of my top-level functions are used only > in one place in the code, I just code them as top-level so that I > can test them in ghci if I need to. No, I don't think using less top-level functions will solve anything. In the case where you don't know how to write a type because it is too complex, or requires features you don't understand, I think it is reasonable to write it, ask GHCI for its type signature, make sure it looks reasonable, and then add it to your file. But I would hope this situation makes up a minority of cases. One could also question the wisdom of writing code that requires type system features you don't understand. -Brent |
In reply to this post by Brent Yorgey-2
Brent Yorgey <byorgey at seas.upenn.edu> writes:
> On Mon, Dec 03, 2012 at 12:28:08PM +0000, Miguel Negrao wrote: >> Is there a syntax in Haskell for partial application that would be something like this the following ? >> >> f a b c d = a +b+ c+ d >> >> g = f _ 1 2 3 >> >> or the only way to do it is like below ? >> >> g = (\x -> f x 1 2 3) > > Yes, a lambda is the only way to do it. In the case where you have fewer (specifically two) variables, you can also use `flip`:: f a b = a / b -- g = f _ 2 can be written as: g = flip f 2 -Keshav |
In reply to this post by Brent Yorgey-2
Brent Yorgey <byorgey at seas.upenn.edu> writes:
> On Mon, Dec 03, 2012 at 03:20:41PM +0000, Miguel Negrao wrote: >> >> A 03/12/2012, ?s 12:53, Brent Yorgey escreveu: >> >> Is there a syntax in Haskell for partial application that would be something like this the following ? >> >> >> >> f a b c d = a +b+ c+ d >> >> >> >> g = f _ 1 2 3 >> > Yes, a lambda is the only way to do it. >> >> Given how compact haskell?s syntax can be, is there a reason why implementing such placeholders is not a good idea for haskell ? > > Yes: it would introduce horrible ambiguity. Consider > > (f (g _ 1 2)) > > Does it mean > > (f (\x -> g x 1 2)) > > or > > (\x -> f (g x 1 2)) > > ? I don't know of any good reason to prefer one over the other. Any > rule you come up with is likely to have other weird corner cases you > hadn't considered. As I understand it, Scala actually does have this > feature, along with lots of confusing, ugly, ad-hoc rules to > disambiguate situations like the above. Another data-point: Mathematica also has this feature, if I correctly understand the above posts [1]. The examples you gave would look like:: (f (g _ 1 2)) ~= f[g[#1, 1, 2]]& (f (\x -> g x 1 2)) ~= f[g[#1, 1, 2]&] (\x -> f (g x 1 2)) ~= f[g[#1, 1, 2]]& So it seems the ambiguity is resolved by having this scope-specifying symbol '&'. [1] http://reference.wolfram.com/mathematica/tutorial/PureFunctions.html -Keshav |
In reply to this post by Brent Yorgey-2
> >
> > g = (\x -> f x 1 2 3) > > Yes, a lambda is the only way to do it. This is not exactly the same thing, but if you have a function that accepts only two arguments, you can use `flip` to partially apply with the other one: f a b = a ++ b g = (flip f) "xyz" g "abc" -- "abcxyz" To extend that to functions with more parameters, you'd have to create an equivalent of `flip` for each arity, and the desired permutations might be more complicated than just reversing them. Still, in the two-argument case, flip can often be cleaner than a lambda. Peter On 3 December 2012 12:53, Brent Yorgey <byorgey at seas.upenn.edu> wrote: > On Mon, Dec 03, 2012 at 12:28:08PM +0000, Miguel Negrao wrote: > > Hi list, > > > > Is there a syntax in Haskell for partial application that would be > something like this the following ? > > > > f a b c d = a +b+ c+ d > > > > g = f _ 1 2 3 > > > > or the only way to do it is like below ? > > > > g = (\x -> f x 1 2 3) > > Yes, a lambda is the only way to do it. > > > Also, hlint complains about top-level functions without type even > > if they are not exported out of the corresponding module. Is is > > really bad style not put type signatures in all top-level functions > > ? I really like the fact that haskell takes care of the type > > signatures for me. > > Yes, it is bad style. Let me give you two reasons why I always > encourage putting type signatures on all top-level functions. Whether > they are exported or not really makes no difference. > > 1. Writing the type signature for a function *first*, before > implementing it, really helps a LOT in clarifying things in your > own mind. If you cannot write down the intended type of a > function then you do not understand what it is supposed to do. > If you do not understand what it is supposed to do then how do > you expect to be able to implement it? > > 2. Suppose you make a mistake when implementing a function. If you > don't give a type signature, it's possible that GHC will infer > some type for it anyway (but not the type you intended!). Now > you will not get an error until further down the line when you > use that function somewhere else. And what's more, the error > will not tell you anything about the real problem. It will just > say "X does not match Y on line 297" and you will have to do a > lot of work to figure out that the real problem is that you > messed up in implementing function foo on line 43. But if you > had put a type signature on foo in the first place, you would > have gotten an error immediately. > > -Brent > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > An HTML attachment was scrubbed... URL: <http://www.haskell.org/pipermail/beginners/attachments/20121205/98eeb691/attachment.htm> |
Free forum by Nabble | Edit this page |