
hello everybody, i'm a newbie this is my first post here.. i have trouble making a function pointfree: data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq) unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a) reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci) -- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26881661.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Here's another way of writing it: data Matrix a = Matr {unMatr :: [[a]]} | Scalar a deriving (Show, Eq) -- RealFrac constraint removed reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes Affixing constraints to type constructors is typically deprecated. slemi wrote:
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
-- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26885392.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

thanks, that's a really neat syntactic sugar :) however, my original question was how to make the reMatr function pointfree, as reMatr = Matr . (flip (.) unMatr) is not working. any ideas/explanation why it doesnt work? Kim-Ee Yeoh wrote:
Here's another way of writing it:
data Matrix a = Matr {unMatr :: [[a]]} | Scalar a deriving (Show, Eq) -- RealFrac constraint removed
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes
Affixing constraints to type constructors is typically deprecated.
slemi wrote:
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
-- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26888978.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Hello, I didn't try to understand what the function is doing, but just quickly noticed that
reMatr a = Matr . (flip (.) unMatr) a
can be written as
reMatr a = Matr . ((flip (.) unMatr) a)
but that
reMatr = Matr . (flip (.) unMatr)
can be written as
reMatr a = (Matr . (flip (.) unMatr)) a
so because of precedence rules a different function is being applied to 'a' in the 2 versions Best Keith On Tue, Dec 22, 2009 at 9:13 AM, slemi <0slemi0@gmail.com> wrote:
thanks, that's a really neat syntactic sugar :)
however, my original question was how to make the reMatr function pointfree, as reMatr = Matr . (flip (.) unMatr) is not working. any ideas/explanation why it doesnt work?
Kim-Ee Yeoh wrote:
Here's another way of writing it:
data Matrix a = Matr {unMatr :: [[a]]} | Scalar a deriving (Show, Eq) -- RealFrac constraint removed
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes
Affixing constraints to type constructors is typically deprecated.
slemi wrote:
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
-- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26888978.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- keithsheppard.name

On Tue, Dec 22, 2009 at 09:27:47AM -0500, Keith Sheppard wrote:
Hello, I didn't try to understand what the function is doing, but just quickly noticed that
reMatr a = Matr . (flip (.) unMatr) a
can be written as
reMatr a = Matr . ((flip (.) unMatr) a)
...and then
reMatr a = (Matr .) ((flip (.) unMatr) a) reMatr a = (Matr .) $ (flip (.) unMatr) a reMatr = (Matr .) . (flip (.) unMatr)
-- Felipe.

There you have it: fully- and semi-pointfree versions of reMatr. A heads up: aggressively pursuing pointfreeness without type signatures guarantees a courtesy call from the monomorphism restriction, pace ()-garlic aficionados. As for your question on why the original code doesn't typecheck: if you explain how you arrived at it, perhaps we can figure out where you tripped up. Daniel Fischer for instance, *calculated* for you the right answer. Habeas calculus and all that. slemi wrote:
thanks, that's a really neat syntactic sugar :)
however, my original question was how to make the reMatr function pointfree, as reMatr = Matr . (flip (.) unMatr) is not working. any ideas/explanation why it doesnt work?
Kim-Ee Yeoh wrote:
Here's another way of writing it:
data Matrix a = Matr {unMatr :: [[a]]} | Scalar a deriving (Show, Eq) -- RealFrac constraint removed
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes
Affixing constraints to type constructors is typically deprecated.
slemi wrote:
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
-- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26897626.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

i dont know any calculus-thingy, this is what i did: reMatr a = Matr . a . unMatr reMatr a = Matr . (. unMatr) a reMatr a = Matr . (flip (.) unMatr) a reMatr = Matr . (flip (.) unMatr) as http://old.nabble.com/pointfree-trouble-td26881661.html#a26889388 Daniel pointed out, this doesnt work because (flip (.) unMatr) takes two arguments. i'm really interested in this calculus stuff, looking up now:) Kim-Ee Yeoh wrote:
There you have it: fully- and semi-pointfree versions of reMatr.
A heads up: aggressively pursuing pointfreeness without type signatures guarantees a courtesy call from the monomorphism restriction, pace ()-garlic aficionados.
As for your question on why the original code doesn't typecheck: if you explain how you arrived at it, perhaps we can figure out where you tripped up. Daniel Fischer for instance, *calculated* for you the right answer. Habeas calculus and all that.
slemi wrote:
thanks, that's a really neat syntactic sugar :)
however, my original question was how to make the reMatr function pointfree, as reMatr = Matr . (flip (.) unMatr) is not working. any ideas/explanation why it doesnt work?
Kim-Ee Yeoh wrote:
Here's another way of writing it:
data Matrix a = Matr {unMatr :: [[a]]} | Scalar a deriving (Show, Eq) -- RealFrac constraint removed
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes
Affixing constraints to type constructors is typically deprecated.
slemi wrote:
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
-- View this message in context: http://old.nabble.com/pointfree-trouble-tp26881661p26902326.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Am Mittwoch 23 Dezember 2009 14:40:46 schrieb slemi:
i dont know any calculus-thingy, this is what i did:
reMatr a = Matr . a . unMatr reMatr a = Matr . (. unMatr) a reMatr a = Matr . (flip (.) unMatr) a
You need to be aware of the implicit parentheses, that is Matr . ((flip (.) unMatr) a) or (.) Matr ((flip (.) unMatr) a) = ((.) Matr) ((flip (.) unMatr) a) = f (g x), with f = (.) Matr g = flip (.) unMatr x = a Now f (g x) = (f . g) x and you're done. But as Kim-Ee Yeoh pointed out, if you're pointfreeing, give type signatures, or the monomorphism restriction is going to surprise you some time.
reMatr = Matr . (flip (.) unMatr)

For the record, all of these compile with -O to exactly the same code!
reMatr1 f m = Matr (f (unMatr m)) reMatr2 f m = Matr $ f $ unMatr m reMatr3 f m = Matr . f . unMatr $ m reMatr4 f = Matr . f . unMatr reMatr5 f = Matr . (flip (.) unMatr) f reMatr6 = (Matr .) . (. unMatr)
And that code is the same as what reMatr1 compiles to with no optimization! Under no optimization, they all compile to direct implementations of their approach - and hence, reMatr1 is the most efficient. The others must wend through quite a number of library functions to do their work. Since there is no real efficiency issue (surely matrix manipulation code will be compiled -O for actual use), the only reason I can see to choose one of these over the other is how it conveys the intention from one programmer to the next. (Or one's self six months later...) In which case seems to me that reMatr4 most cleanly encapsulates the programmer's intention. Of course, I've had some Haskell experience and I get the idiom - to someone less versed in Haskell, reMatr1 is probably the clearest - to someone with much Haskell experience, perhaps reMatr6, though it just looks "clever" to me, rather than clear. I'm curious why the original poster was motivated to pursue pointfree style to the point of no explicit arguments? - Mark

Am Freitag 25 Dezember 2009 00:19:58 schrieb Mark Lentczner:
For the record, all of these compile with -O to exactly the same code!
reMatr1 f m = Matr (f (unMatr m)) reMatr2 f m = Matr $ f $ unMatr m reMatr3 f m = Matr . f . unMatr $ m reMatr4 f = Matr . f . unMatr reMatr5 f = Matr . (flip (.) unMatr) f reMatr6 = (Matr .) . (. unMatr)
And that code is the same as what reMatr1 compiles to with no optimization!
Under no optimization, they all compile to direct implementations of their approach - and hence, reMatr1 is the most efficient. The others must wend through quite a number of library functions to do their work.
Yes, GHC doesn't inline across module boundaries without optimisations.
Since there is no real efficiency issue (surely matrix manipulation code will be compiled -O for actual use), the only reason I can see to choose one of these over the other is how it conveys the intention from one programmer to the next. (Or one's self six months later...) In which case seems to me that reMatr4 most cleanly encapsulates the programmer's intention.
I think so, too. Version 1 is fine, too. Version 2 could be okay if the function had a longer name than f, as it is, the f is squashed by the two adjacent $s. Version 3 is not a good point to stop on the way from 1 to 4 IMO.
Of course, I've had some Haskell experience and I get the idiom - to someone less versed in Haskell, reMatr1 is probably the clearest - to someone with much Haskell experience, perhaps reMatr6, though it just looks "clever" to me, rather than clear.
It's easy enough to understand with sufficient experience, and among the completely pointfree versions, I think it's the clearest (also clearer than version 5, although that's not yet completely point free). But although it's fairly benign, it already shows that completely pointfree style tends to obfuscate except in the simplest cases.
I'm curious why the original poster was motivated to pursue pointfree style to the point of no explicit arguments?
I can't speak for the OP, but pointfreeing is always an interesting mental exercise, it's often fun to push it deep into obfuscation just for the heck of it. But, more importantly, you learn to understand the combinators better, and you develop a sense of how far to go with pointfreeing.

On Tue, Dec 22, 2009 at 12:50:26AM -0800, Kim-Ee Yeoh wrote:
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr f = Matr . f . unMatr -- this idiom occurs a lot, esp. with newtypes
And usually we would call this 'liftMatr' or something along these lines. The function "lifts" one function from one domain to another one. -- Felipe.

Am Dienstag 22 Dezember 2009 15:09:34 schrieb slemi:
hello everybody, i'm a newbie this is my first post here..
i have trouble making a function pointfree:
data RealFrac a => Matrix a = Matr [[a]] | Scalar a deriving (Show, Eq)
unMatr :: RealFrac a => Matrix a -> [[a]] unMatr = (\(Matr a) -> a)
reMatr :: RealFrac a => ([[a]] -> [[a]]) -> (Matrix a -> Matrix a) reMatr a = Matr . (flip (.) unMatr) a
this works fine, but if i leave the 'a' in the last function's definition like this: reMatr = Matr . (flip (.) unMatr) it gives an error. can anybody tell me why? (i'm using ghci)
You want reMatr f = Matr . f . unMatr = (.) Matr (f . unMatr) = (.) Matr ((.) f unMatr) = (.) Matr (flip (.) unMatr f) = (.) Matr ((flip (.) unMatr) f) = (((.) Matr) . (flip (.) unMatr)) f So reMatr = ((.) Matr) . (flip (.) unMatr) Or, as I prefer it, reMatr = (Matr .) . (. unMatr) The point is that g = flip (.) unMatr [or (. unMatr)] takes two arguments, the function f and a matrix m, to yield an argument fitting for Matr, so we need to apply one argument before we can compose it with Matr, hence we compose it with (compose with Matr) = (.) Matr = (Matr .): (Matr .) . g
participants (7)
-
Chaddaï Fouché
-
Daniel Fischer
-
Felipe Lessa
-
Keith Sheppard
-
Kim-Ee Yeoh
-
Mark Lentczner
-
slemi