A little F# for you
-
Thats simply a map/reduce pattern, also called folding. Here is a Scheme example:
(define (fold func accum lst)
(if (null? lst)
accum
(fold func (func accum (car lst)) (cdr lst))))(define (sum . lst) (fold + 0 lst))
(display "sum = ")
(display (sum 1 2 3)) ; prints 6 (0 + 1 + 2 + 3)
(newline)(define (product . lst) (fold * 1 lst))
(display "product = ")
(display (product 1 2 3)) ; prints 6 (1 * 1 * 2 * 3)xacc.ide
The rule of three: "The first time you notice something that might repeat, don't generalize it. The second time the situation occurs, develop in a similar fashion -- possibly even copy/paste -- but don't generalize yet. On the third time, look to generalize the approach."Wow. That takes me back. Haven't seen that stuff since college.
"If you think of yourselves as helpless and ineffectual, it is certain that you will create a despotic government to be your master. The wise despot, therefore, maintains among his subjects a popular sense that they are helpless and ineffectual." - Frank Herbert
-
That looks like a huge advancement in clarity and code maintainability. (Where's the sarcasm icon when I need it)
cheers, Chris Maunder
CodeProject.com : C++ MVP
(Where's the sarcasm icon when I need it) This is all we got to work with: :rolleyes:
Christianity: The belief that a cosmic Jewish zombie who was his own father can make you live forever if you symbolically eat his flesh and telepathically tell him you accept him as your master, so he can remove and evil force from your soul that is present in humanity because a rib-woman was convinced by a talking snake to eat from a magical tree... yeah, makes perfect sense.
-
It's been so long since that's happened.
Brady Kelly wrote:
It's been so long since that's happened.
What are we talkin', days? weeks?
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
Steve Echols wrote:
Whoa!
My sentiments exactly! The hardest part about learning F#, for me, is the fact that it has both new syntax and new concepts (well, new for me anyways). I must say, though, that I haven't had this much geeky fun in a long time! There's nothing better than freeing your mind a little bit, and thinking about things from a totally different perspective. :-D
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
It's vaguely familiar, though... Prolog, maybe?
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
-
Brady Kelly wrote:
It's been so long since that's happened.
What are we talkin', days? weeks?
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
I exagerate, but just the other night I woke up with my face in a chapter on the ASP.NET 2.0 request handling chain.
-
Rama Krishna Vavilala wrote:
of WPF or F#?
I meant WPF. I don't even know where the surface of F# is yet! :)
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
You are being very modest.:) Was it because I mentioned Karen contacted you for WPF in Action review or where you in the game before.:)
Co-Author ASP.NET AJAX in Action
-
You are being very modest.:) Was it because I mentioned Karen contacted you for WPF in Action review or where you in the game before.:)
Co-Author ASP.NET AJAX in Action
Rama Krishna Vavilala wrote:
Was it because I mentioned Karen contacted you for WPF in Action review or where you in the game before.
Oh, was it you who got them in touch with me? Thanks a lot! :-D
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
I've been studying F# a lot recently and find it really mind-bending. Tomas Petricek, a fellow CPian, let me sneak preview his series of F# articles and they are very good. I took one of his examples and modified it a bit. The following code displays "sum = 6", but how that happens is other-worldly...check it out:
#light
let rec sum nums =
match nums with
| head::tail -> head + sum(tail)
| [] -> 0
printf "sum = %i" (sum [1; 2; 3])Weird, eh? F# is coooool. :cool:
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
Huh, I hope that this code is being written automatically by dragging Sum and Numbers controls from toolbox and dropping them on a page:) Moreover, 5th line looks like a smiley |[]->0 .
sacoskun wrote:
Huh, I hope that this code is being written automatically by dragging Sum and Numbers controls from toolbox and dropping them on a page
Yeah, and that little dog in the Windows Explorer Search screen barks at you while you drag stuff around. :rolleyes:
sacoskun wrote:
Moreover, 5th line looks like a smiley |[]->0
Wow, good catch!!
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
I've been studying F# a lot recently and find it really mind-bending. Tomas Petricek, a fellow CPian, let me sneak preview his series of F# articles and they are very good. I took one of his examples and modified it a bit. The following code displays "sum = 6", but how that happens is other-worldly...check it out:
#light
let rec sum nums =
match nums with
| head::tail -> head + sum(tail)
| [] -> 0
printf "sum = %i" (sum [1; 2; 3])Weird, eh? F# is coooool. :cool:
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
Cool - your next task is to learn a) how to apply implicitly recursive functions like
fold
andmap
rather than explicit recursion, and b) recognise when they can be applied. To use your example, except using Haskell, 'cause that's what I like: Explicit recursion:sum [] = 0 sum (head:tail) = head + (sum tail)
Differences from F# - recursion and pattern matching don't need to be explicitly stated. Oh, and if you ask Haskell what the type of
sum
is, it'll reply with(Num t) => [t] -> t
- basically saying thatsum
is now defined for lists of any numeric type...polymorphism at work - uber cool! Implicit recursion:sum = foldl (+) 0
A fold combines all elements of a collection using some function - so
sum
combines all elements of a list using the + operator (Haskell lets you use operator as functions if you surround them with brackets) starting with the accumulating value set to zero. Oh - and even though I've not defined any parameters to this sum definition, it does take one -sum
is defined as a partial application offoldl
, so it's equivalent tosum nums = foldl (+) 0 nums
. Oh - and this definition ofsum
is defined over all numeric lists as well :-) - the type offoldl
is(a -> b -> a) -> a -> [b] -> a
-a
andb
are arbitrary types,(+)
has type(Num a) => a -> a -> a
and0
has type(Num t) => t
. Combine those types all together and you get the same as the first definition ofsum
! OK - I'm an FP language dweeb, I'll admit it... -
Cool - your next task is to learn a) how to apply implicitly recursive functions like
fold
andmap
rather than explicit recursion, and b) recognise when they can be applied. To use your example, except using Haskell, 'cause that's what I like: Explicit recursion:sum [] = 0 sum (head:tail) = head + (sum tail)
Differences from F# - recursion and pattern matching don't need to be explicitly stated. Oh, and if you ask Haskell what the type of
sum
is, it'll reply with(Num t) => [t] -> t
- basically saying thatsum
is now defined for lists of any numeric type...polymorphism at work - uber cool! Implicit recursion:sum = foldl (+) 0
A fold combines all elements of a collection using some function - so
sum
combines all elements of a list using the + operator (Haskell lets you use operator as functions if you surround them with brackets) starting with the accumulating value set to zero. Oh - and even though I've not defined any parameters to this sum definition, it does take one -sum
is defined as a partial application offoldl
, so it's equivalent tosum nums = foldl (+) 0 nums
. Oh - and this definition ofsum
is defined over all numeric lists as well :-) - the type offoldl
is(a -> b -> a) -> a -> [b] -> a
-a
andb
are arbitrary types,(+)
has type(Num a) => a -> a -> a
and0
has type(Num t) => t
. Combine those types all together and you get the same as the first definition ofsum
! OK - I'm an FP language dweeb, I'll admit it...Stuart Dootson wrote:
OK - I'm an FP language dweeb, I'll admit it...
Wow, but you're one knowledgable FP language dweeb! Thanks for sharing that with me. I'll have to study what you wrote, to make sure it sticks.
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
Josh Smith wrote:
'head::tail' means "if it exists, remove the first item in the list
Wouldnt that just destructure your input list into 'head' and 'tail' variable? Perhaps the '::' has special meaning? :confused:
xacc.ide
The rule of three: "The first time you notice something that might repeat, don't generalize it. The second time the situation occurs, develop in a similar fashion -- possibly even copy/paste -- but don't generalize yet. On the third time, look to generalize the approach."leppie wrote:
Wouldnt that just destructure your input list into 'head' and 'tail' variable?
When used on the left hand side of a pattern match, yes. When used on the right hand side, it's just a cons operator (i.e. adds an element to the front of a list). So,
blah head::tail -> head::tail
leaves the list unchanged. -
Chris Maunder wrote:
That looks like a huge advancement in clarity and code maintainability.
Hahaha. Yeah right. I get the feeling that F# isn't going to become a "mainstream" .NET language anytime soon. It's out there: far, far out there. It has virtues different from clarity and code maintainability. I'm just a newbie so don't quote me, but supposedly using F# as a functional programming language allows you to more easily write code which can be parallelized across multiple processors or cores. I'm interested to see how to do that, because I think that's an important aspect of modern software design.
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
-
Steve Echols wrote:
Whoa!
My sentiments exactly! The hardest part about learning F#, for me, is the fact that it has both new syntax and new concepts (well, new for me anyways). I must say, though, that I haven't had this much geeky fun in a long time! There's nothing better than freeing your mind a little bit, and thinking about things from a totally different perspective. :-D
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
Josh Smith wrote:
There's nothing better than freeing your mind a little bit,
As long as it does not fall out and get lost in the process :)
Rocky <>< Blog Post: MVC for ASP.NET! Tech Blog Post: Cheap Biofuels and Synthetics coming soon? Tech Sites: SilverlightCity.com ~ TheSilverlightDirectory.com ~ TheWPFDirectory.com
-
If it took me almost 7 years to start coding in .net, you can imagine how excited I am about F#...
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001:laugh:
Rocky <>< Blog Post: MVC for ASP.NET! Tech Blog Post: Cheap Biofuels and Synthetics coming soon? Tech Sites: SilverlightCity.com ~ TheSilverlightDirectory.com ~ TheWPFDirectory.com
-
Having studied Miranda for far longer than humanely reasonable, nearly 6 months, the example given just looks like a very syntactically ineffecient list comprehension. List comprehensions are fantastically powerful once you've wrapped your head around how to use them. There is a more fundamental problem here though:- Purely functional and declarative languages set out to tell the computer what result you want but provide no way to specify how the computer is to get the result, or what it should do with it. Purely procedural languages tell the computer exactly what to do but it's very hard for a person to determine from reading one what the expected result might be. Both of these approaches have merit but are only properly leveraged when they are 'pure'. As soon as you mix the concepts together you loose the benefits of both without gaining the advantages of either. The worst aspects of C++ for example are the ones that are partially declarative at run time like, There exists a giblet called thing => giblet thing = new giblet;. These areas are where the opaqueness that causes most problems with learning, correctness and performance come in. As F# appears, like 'managed' C++ to be an attempt to mix these approaches, albeit biased towards the functional I guess it will fail just as spectacularly. What is really needed is a pure functional language that manipulates primitives which themsleves are purely procedural components, a kind of functional COM. stl gets a little way and Boost a little further but both are hamstrung by language limitations. We're not there yet :)
Nothing is exactly what it seems but everything with seems can be unpicked.
Can you reply to any post without at least a few paragraphs that require reading more than once? Are you in anyway related to the Grand Negus?
-
If it took me almost 7 years to start coding in .net, you can imagine how excited I am about F#...
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001 -
Cool - your next task is to learn a) how to apply implicitly recursive functions like
fold
andmap
rather than explicit recursion, and b) recognise when they can be applied. To use your example, except using Haskell, 'cause that's what I like: Explicit recursion:sum [] = 0 sum (head:tail) = head + (sum tail)
Differences from F# - recursion and pattern matching don't need to be explicitly stated. Oh, and if you ask Haskell what the type of
sum
is, it'll reply with(Num t) => [t] -> t
- basically saying thatsum
is now defined for lists of any numeric type...polymorphism at work - uber cool! Implicit recursion:sum = foldl (+) 0
A fold combines all elements of a collection using some function - so
sum
combines all elements of a list using the + operator (Haskell lets you use operator as functions if you surround them with brackets) starting with the accumulating value set to zero. Oh - and even though I've not defined any parameters to this sum definition, it does take one -sum
is defined as a partial application offoldl
, so it's equivalent tosum nums = foldl (+) 0 nums
. Oh - and this definition ofsum
is defined over all numeric lists as well :-) - the type offoldl
is(a -> b -> a) -> a -> [b] -> a
-a
andb
are arbitrary types,(+)
has type(Num a) => a -> a -> a
and0
has type(Num t) => t
. Combine those types all together and you get the same as the first definition ofsum
! OK - I'm an FP language dweeb, I'll admit it...Well, I read this and I'm still not sure I get it. Aah - wait a second, with my mathematician head on I get it.
Deja View - the feeling that you've seen this post before.
-
I've been studying F# a lot recently and find it really mind-bending. Tomas Petricek, a fellow CPian, let me sneak preview his series of F# articles and they are very good. I took one of his examples and modified it a bit. The following code displays "sum = 6", but how that happens is other-worldly...check it out:
#light
let rec sum nums =
match nums with
| head::tail -> head + sum(tail)
| [] -> 0
printf "sum = %i" (sum [1; 2; 3])Weird, eh? F# is coooool. :cool:
:josh: My WPF Blog[^] Without a strive for perfection I would be terribly bored.
Perl made entirely from Regexes and then encrypted in Hex, is still more understandable than that. What's wrong with debug.Print("Sum = 6");
Ninja (the Nerd)
Confused? You will be... -
Well, I read this and I'm still not sure I get it. Aah - wait a second, with my mathematician head on I get it.
Deja View - the feeling that you've seen this post before.
OK - lets do it in C++... Explicit recursion:
template<class ListIter> std::iterator_traits<ListIter>::value_type sum(ListIter begin, ListIter end) { if (begin == end) return 0; // == sum [] = 0 if (begin != end) return (*begin) + sum(begin+1, end); // == sum (head:tail) = head + (sum tail) ... well, kind of }
Implicit recursion:
template<class ListIter> std::iterator_traits<ListIter>::value_type sum(ListIter begin, ListIter end) { return std::accumulate(begin, end, 0, std::plus<std::iterator_traits<ListIter>::value_type>()); }
We're representing lists using the pair
(ListIter begin, ListIter end)
and the set of types for which this compiles is less easy to determine, but that aside it's pretty much the same as the Haskell code, even down to being polymorphic. In C++,std::transform
==map
andstd::accumulate
==foldl
.