Also, see the end of this post for an example of a functional bubble sort (and for examples of removing for/while loops in favor of tail recursion). Note that while the sort itself carries no mutable state, it operates against a mutable array, which would be easy to fix by cloning the array first.
something like this?
something like this?
Thanks, the Binary Tree on this blog is very good.
On that blog, there is also implementation of Stack, so I wrote Stack on my own. I tried to write it as simple as possible, what do you think guys?
Here it is:
//STACKtype Stack = | Empty | Link of int * Stack let isEmpty = function | Empty -> true | _ -> false let rec push = function | x, Link(y, m) -> Link(y, push(x, m)) | x, Empty -> Link(x, Empty) let rec pop = function | Link(x, l) when l <> Empty -> Link(x, pop l) | Link(x, Empty) -> Empty | _ -> Empty let rec top = function | Link(x, m) when m <> Empty -> top m | Link(x, m) when m = Empty -> printfn "Top of the stack: %A" x | _ -> () let s1 = Link (0, Link(1, Link(2, Link(3, Empty))))printfn "Stack s1: %A\nisEmpty: %b" s1 (isEmpty s1)let s2 = Emptyprintfn "Stack s2: %A\nisEmpty: %b" s2 (isEmpty s2)let s3 = push(111, s2)printfn "Stack s3: %A\nisEmpty: %b" s3 (isEmpty s3)let s4 = push(222, s1)printfn "Stack s4: %A\nisEmpty: %b" s4 (isEmpty s4)top s1let s5 = pop s1printfn "Stack s5: %A\nisEmpty: %b" s5 (isEmpty s5)
Implementing stacks and linked-lists yourself is a great way to learn about functional programming. However, just to let you know, the List type (linked list) is built into the language. Refactoring the other examples here using the built-in list type gives:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#light let isEmpty = function | [] -> true | _ -> false let push x s = x :: s let pop = function | x :: s -> s | [] -> failwith "pop: empty stack." let top = function | x :: s -> x | [] -> failwith "top: empty stack." let rec iter f s = if not (isEmpty s) then f (top s) iter f (pop s) else () > val isEmpty : 'a list -> bool val push : 'a -> 'a list -> 'a list val pop : 'a list -> 'a list val top : 'a list -> 'a val iter : ('a -> unit) -> 'a list -> unit > let s = [] |> push 3 |> push 2 |> push 1 |> push 0 iter (fun v -> printfn "%A" v) s > val s : int list 0 1 2 3
Note further that there are built-in higher-order functions, like "iter" above, for iterating, mapping, searching, and otherwise transforming Lists, Sequences, Maps, and Sets.
For example, List.iter produces the same output as "iter" above:
1 2 3 4 5 6 7 8 9 10
List.iter (fun v -> printfn "%A" v) s > val s : int list 0 1 2 3
Hi,
That's a good beginning. I have a few comments:
* your type should be generic: "type Stack<'a> = ..."
* isEmpty could be written: let isEmpty x = x = Empty (or even: let isEmpty = (=) Empty )
* your top function should return a value (instead of printing it). It will be easier to use in real code.
* for the push function, it's a better style to write a function with two arguments instead of one tuple (it enables partial application)
* push, pop and top shouldn't be recursive. You should add values on top
(rather than on bottom).
Here is how I would write it:
type Stack<'a> =
| Empty
| Link of 'a * Stack<'a>
let isEmpty x = x = Empty
let push x s = Link(x, s)
let pop = function
| Link(_, s) -> s
| _ -> Empty // you could throw an exception here
let top = function
| Link(x, _) -> x
| _ -> invalidArg "top" "Empty stack"
Tests (yes, I like the pipe operator):
let s = Empty |> push 3 |> push 2 |> push 1 |> push 0
s |> top |> printfn "%A"
s |> pop |> top |> printfn "%A"
s |> pop |> pop |> top |> printfn "%A"
As an exercise, you could now try the Queue type (this time, you'll probably need recursive functions).
Laurent.
Hi,
I'm learning immensly from this thread. Thanks everyone. One question, how do I change the pop function so pop returns the last value in, and takes it out of the stack.
Many thanks.
Joe
Because a functional Stack would be immutable, you could rewrite pop to return a tuple composed of the head value and the remaining stack:
1 2 3 4 5 6 7 8 9 10 11 12
let pop = function | x :: s -> x, s | [] -> failwith "pop: empty stack." let myStack = [1; 2; 3] let h, s = pop myStack printfn "%d" h // 1 printfn "%A" s // [2; 3] printfn "%A" myStack // [1; 2; 3]
Hi,
That's a good beginning. I have a few comments:
* your type should be generic: "type Stack<'a> = ..."
* isEmpty could be written: let isEmpty x = x = Empty (or even: let isEmpty = (=) Empty )
* your top function should return a value (instead of printing it). It will be easier to use in real code.
* for the push function, it's a better style to write a function with two arguments instead of one tuple (it enables partial application)
* push, pop and top shouldn't be recursive. You should add values on top
(rather than on bottom).
Hello,
with generic, you mean that when declaring Stack type, I use 'a instead of int in 'Link'?
Here I changed Top (returns value) and Push(can be curried) functions as you suggested:
let rec push2 x s = match s with
| Link(y, m) -> Link(y, push(x, m))
| Empty -> Link(x, Empty)
let rec top2 = function
| Link(x, Empty) -> x
| Link(x, m) -> top2 m
| _ -> -1
Your implementation seems to me quite nice. I haven't learned about '|>' operator yet, so I am not sure how exactly does it works.Why do you guys think, recursion is not suitable for this case? Just because its slower when adding to end?
I haven't learned about '|>' operator yet, so I am not sure how exactly does it works.
The forward pipe operator (|>) is defined as follows:
1 2 3 4 5 6
let (|>) g f = f g > val ( |> ) : 'a -> ('a -> 'b) -> 'b
All it does is take the left-side argument and apply it to the function specified on the right. What this does, though, is allows the compiler to see the type of the left-side argument BEFORE the function on the right, and this often helps the type-inferrer figure out types on the right-side.
Here is an example from my last post, rewritten with forward-pipe (though there is nothing for the type inferrer to do, it is considered "better" F# style).
1 2 3 4 5 6 7 8 9 10
s |> iter (fun v -> printfn "%A" v) > 0 1 2 3
Why do you guys think, recursion is not suitable for this case? Just because its slower when adding to end?
<i>If for no other reason<i> than it is (very significantly) slower. You will traverse the entire list <i>every time you get top<i>, which makes the difference between running in O(1) vs O(n^D), where D is the stack depth.
I think the ``top'' function returns the bottom of the stack. Also, I prefer the construction of ``pop'' to the ``top'', because there is no need for the when clause:
1 2 3 4 5 6 7 8
let rec bottom = function | Link(x, Empty) -> x | Link(x, m) -> bottom m | Empty -> Empty
It seems to me like a pretty clean implementation of a stack.
I think the ``top'' function returns the bottom of the stack. Also, I prefer the construction of ``pop'' to the ``top'', because there is no need for the when clause:
1 2 3 4 5 6 7 8let rec bottom = function | Link(x, Empty) -> x | Link(x, m) -> bottom m | Empty -> EmptyIt seems to me like a pretty clean implementation of a stack.
'Top' function of stack should return last added (top) item. It does in my implementation. But you are right as well, because in fact, returned item is bottom item in this Stack. It was my intention do code it like this and this way is best suitable for recursion. I think this data structure behaves like Stack, even if doesn't look so. :)
Yes, 'when' clause is useless here.
I should have looked a little closer. I assumed that you were adding to the front in O(1), as in Laurent's implementation. As it is, your implementation adds and pops in O(n), always acting on the back.
Anyway, if you implement a queue you'll see that either enqueue or dequeue should be O(n). But, not both. (And, you'll still get to use recursion without it being superfluous).
Good luck.
I think the ``top'' function returns the bottom of the stack. Also, I prefer the construction of ``pop'' to the ``top'', because there is no need for the when clause:
1 2 3 4 5 6 7 8let rec bottom = function | Link(x, Empty) -> x | Link(x, m) -> bottom m | Empty -> EmptyIt seems to me like a pretty clean implementation of a stack.
'Top' function of stack should return last added (top) item. It does in my implementation. But you are right as well, because in fact, returned item is bottom item in this Stack. It was my intention do code it like this and this way is best suitable for recursion. I think this data structure behaves like Stack, even if doesn't look so. :)
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hello,
I am F# noob (learning it for a week or so) and I was thinking, how to implement e.g. Binary Tree, or just Bubble sort in pure functional way. Without changing of value (not using mutable), etc. and I didn't solve it.
Could anyone give me a hint?