├── .editorconfig ├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── .travis.yml ├── ExtCore.Benchmarks ├── Collections.IntMap.fs ├── Collections.IntSet.fs ├── ExtCore.Benchmarks.fsproj └── Program.fs ├── ExtCore.Tests ├── Args.fs ├── Caching.LruCache.fs ├── Collections.Array.fs ├── Collections.ArrayView.fs ├── Collections.AsyncSeq.fs ├── Collections.Bimap.fs ├── Collections.Dict.fs ├── Collections.HashMap.fs ├── Collections.HashSet.fs ├── Collections.IntBimap.fs ├── Collections.IntMap.fs ├── Collections.IntSet.fs ├── Collections.LazyList.fs ├── Collections.List.fs ├── Collections.ListZipper.fs ├── Collections.LongBimap.fs ├── Collections.LongMap.fs ├── Collections.LongSet.fs ├── Collections.Map.fs ├── Collections.Multimap.fs ├── Collections.Multiset.fs ├── Collections.PriorityQueue.fs ├── Collections.Queue.fs ├── Collections.Range.fs ├── Collections.ResizeArray.fs ├── Collections.Seq.fs ├── Collections.Set.fs ├── Collections.Vector.fs ├── Collections.VectorView.fs ├── Control.Agents.fs ├── Control.Cps.fs ├── Control.Observable.fs ├── Control.fs ├── ControlCollections.Async.fs ├── ControlCollections.AsyncChoice.fs ├── ControlCollections.AsyncMaybe.fs ├── ControlCollections.AsyncProtectedState.fs ├── ControlCollections.AsyncState.fs ├── ControlCollections.Choice.fs ├── ControlCollections.Cont.fs ├── ControlCollections.Maybe.fs ├── ControlCollections.ProtectedState.fs ├── ControlCollections.Reader.fs ├── ControlCollections.ReaderChoice.fs ├── ControlCollections.ReaderMaybe.fs ├── ControlCollections.ReaderProtectedState.fs ├── ControlCollections.ReaderState.fs ├── ControlCollections.State.fs ├── ControlCollections.StateCont.fs ├── ControlCollections.StatefulChoice.fs ├── ExtCore.Tests.fsproj ├── IO.fs ├── NativeInterop.fs ├── Net.fs ├── Pervasive.fs ├── RefCountEnumerable.fs ├── String.fs ├── Substring.fs ├── TestHelpers.fs ├── app.config └── packages.config ├── ExtCore.sln ├── ExtCore ├── Args.fs ├── AssemblyInfo.fs ├── Caching.LruCache.fs ├── Collections.Array.fs ├── Collections.ArrayView.fs ├── Collections.AsyncSeq.fs ├── Collections.Bimap.fs ├── Collections.Dict.fs ├── Collections.HashMap.fs ├── Collections.HashSet.fs ├── Collections.IntBimap.fs ├── Collections.IntMap.fs ├── Collections.IntSet.fs ├── Collections.LazyList.fs ├── Collections.List.fs ├── Collections.ListZipper.fs ├── Collections.LongBimap.fs ├── Collections.LongMap.fs ├── Collections.LongSet.fs ├── Collections.Map.fs ├── Collections.Multimap.fs ├── Collections.Multiset.fs ├── Collections.PriorityQueue.fs ├── Collections.Queue.fs ├── Collections.ResizeArray.fs ├── Collections.Seq.fs ├── Collections.Set.fs ├── Collections.TaggedArray.fs ├── Collections.Vector.fs ├── Collections.VectorView.fs ├── Collections.fs ├── Control.Agents.fs ├── Control.Cps.fs ├── Control.Indexed.fs ├── Control.Observable.fs ├── Control.Tasks.fs ├── Control.fs ├── ControlCollections.Async.fs ├── ControlCollections.AsyncChoice.fs ├── ControlCollections.AsyncMaybe.fs ├── ControlCollections.AsyncProtectedState.fs ├── ControlCollections.AsyncState.fs ├── ControlCollections.Choice.fs ├── ControlCollections.Cont.fs ├── ControlCollections.Maybe.fs ├── ControlCollections.ProtectedState.fs ├── ControlCollections.Reader.fs ├── ControlCollections.ReaderChoice.fs ├── ControlCollections.ReaderMaybe.fs ├── ControlCollections.ReaderProtectedState.fs ├── ControlCollections.ReaderState.fs ├── ControlCollections.State.fs ├── ControlCollections.StateCont.fs ├── ControlCollections.StatefulChoice.fs ├── ExtCore.fsproj ├── ExtraPervasives.fs ├── IO.fs ├── NativeInterop.fs ├── Net.fs ├── Pervasive.fs ├── String.fs └── Substring.fs ├── LICENSE.txt ├── README.rst ├── _docs ├── Changelog.rst ├── References.rst └── TODO.rst ├── appveyor.yml ├── install_dotnet.ps1 ├── packages └── repositories.config └── proto-compile /.editorconfig: -------------------------------------------------------------------------------- 1 | ; Top-most EditorConfig file 2 | root = true 3 | 4 | ; Global settings 5 | [*] 6 | ;end_of_line = LF ; Unix-style newlines 7 | indent_size = 4 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | ; F# source files 13 | [*.fs] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | ; F# interface specifications 18 | [*.fsi] 19 | indent_style = space 20 | indent_size = 4 21 | 22 | ; F# lexer specifications 23 | [*.fsl] 24 | indent_style = space 25 | indent_size = 4 26 | 27 | ; F# parser specifications 28 | [*.fsy] 29 | indent_style = space 30 | indent_size = 4 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # General (non-project-specific) patterns 3 | ############################################################################### 4 | 5 | # OS junk files 6 | *.DS_Store 7 | [Tt]humbs.db 8 | 9 | # Temp Files 10 | *~ # UNIX 11 | ~$* # Microsoft Office 12 | 13 | # Bindings for other source-control systems. 14 | .hg 15 | .svn 16 | 17 | # .NET / Visual Studio (Folders) 18 | ipch/ 19 | obj/ 20 | [Bb]in 21 | [Dd]ebug*/ 22 | [Rr]elease*/ 23 | 24 | # .NET / Visual Studio (Files) 25 | *_i.c 26 | *_p.c 27 | *.aps 28 | *.bak 29 | *.[Cc]ache 30 | *.exe 31 | *.gpState 32 | *.ilk 33 | *.log 34 | *.lib 35 | *.ncb 36 | *.[Oo]bj 37 | *.opensdf 38 | *.pch 39 | *.pdb 40 | *.res 41 | *.resources 42 | *.sbr 43 | *.sdf 44 | *.sln.cache 45 | *.suo 46 | *.tlb 47 | *.tlh 48 | *.user 49 | *.vspscc 50 | *.vssscc 51 | Ankh.NoLoad 52 | 53 | # NuGet 54 | !.nuget/* 55 | [Pp]ackages/* 56 | ![Pp]ackages/repositories.config 57 | 58 | # Visual Studio (Project Upgrade) 59 | Backup/ 60 | _UpgradeReport_Files/ 61 | UpgradeLog.htm 62 | UpgradeLog.XML 63 | 64 | # Test Results 65 | [Tt]est[Rr]esult* 66 | TestResults/ 67 | TestResult.xml 68 | 69 | # 3rd-party Tools 70 | _ReSharper*/ 71 | *.nvuser 72 | *.resharper 73 | *resharper.user 74 | *.sln.DotSettings 75 | 76 | # Build Output 77 | #pkg 78 | [Bb]uild 79 | /_build/* 80 | 81 | 82 | ############################################################################### 83 | # Project-specific patterns 84 | ############################################################################### 85 | 86 | # Ignore the tools folder (where e.g., NUnit.Runners is unpacked) 87 | [Tt]ools 88 | 89 | # Ignore the NuGet build folder, it's only needed when building the package 90 | _NuGetBuild/* 91 | .idea/ -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jack-pappas/ExtCore/86ff5620eee77b972ee3e929b982b189c6fe355d/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 32 | 33 | 34 | 35 | 36 | $(SolutionDir).nuget 37 | packages.config 38 | 39 | 40 | 41 | 42 | $(NuGetToolsPath)\NuGet.exe 43 | @(PackageSource) 44 | 45 | "$(NuGetExePath)" 46 | mono --runtime=v4.0.30319 $(NuGetExePath) 47 | 48 | $(TargetDir.Trim('\\')) 49 | 50 | -RequireConsent 51 | -NonInteractive 52 | 53 | "$(SolutionDir) " 54 | "$(SolutionDir)" 55 | 56 | 57 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) 58 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 59 | 60 | 61 | 62 | RestorePackages; 63 | $(BuildDependsOn); 64 | 65 | 66 | 67 | 68 | $(BuildDependsOn); 69 | BuildPackage; 70 | 71 | 72 | 73 | 74 | 75 | 76 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | 98 | 100 | 101 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | 3 | # Use container-based infrastructure with Ubuntu Trusty (14.04) 4 | os: linux 5 | dist: trusty 6 | sudo: required 7 | 8 | # TODO : Enable both mono and dotnet builds: https://docs.travis-ci.com/user/languages/csharp/#Testing-Against-Mono-and-.NET-Core 9 | mono: 10 | - latest 11 | 12 | matrix: 13 | include: 14 | - dotnet: 2.0.0 15 | env: 16 | - DOTNETLIBFW=netstandard2.0 17 | - DOTNETFW=netcoreapp2.0 18 | - MONO_BASE_PATH=/usr/lib/mono/ 19 | - dotnet: 1.1.0 20 | env: 21 | - DOTNETLIBFW=netstandard1.6 22 | - DOTNETFW=netcoreapp1.1 23 | - MONO_BASE_PATH=/usr/lib/mono/ 24 | 25 | install: 26 | - dotnet restore 27 | 28 | # TODO : Add before_script section to clone fsharp/fsharp repo and compile it, so fsc-proto can be used. 29 | # Cache the compiled fsharp build (using travis CI caching functionality) so it doesn't have to run every time. 30 | # TODO : Use build matrix to run two jobs; one where we build/test via the solution, and another where we build through proto-compile 31 | # https://docs.travis-ci.com/user/customizing-the-build/#Explicitly-Including-Jobs 32 | 33 | script: 34 | - dotnet build ExtCore/ExtCore.fsproj --framework $DOTNETLIBFW 35 | - FrameworkPathOverride=$MONO_BASE_PATH/4.5-api/ dotnet build ExtCore/ExtCore.fsproj --framework "net45" 36 | - dotnet test ExtCore.Tests/ExtCore.Tests.fsproj --framework $DOTNETFW 37 | # - FrameworkPathOverride=$MONO_BASE_PATH/4.5-api/ dotnet test ExtCore.Tests/ExtCore.Tests.fsproj --framework "net45" 38 | # Workaround for dotnet test on net45: 39 | - FrameworkPathOverride=$MONO_BASE_PATH/4.5-api/ dotnet build ExtCore.Tests/ExtCore.Tests.fsproj --framework "net45" 40 | - nuget install NUnit.ConsoleRunner -Version 3.7.0 -OutputDirectory $PWD/packages 41 | - mono packages/NUnit.ConsoleRunner.3.7.0/tools/nunit3-console.exe ExtCore.Tests/bin/Debug/net45/ExtCore.Tests.dll 42 | 43 | -------------------------------------------------------------------------------- /ExtCore.Benchmarks/Collections.IntMap.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2018 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace Benchmarks.ExtCore.Collections.IntMap 20 | 21 | open System 22 | open BenchmarkDotNet.Attributes 23 | 24 | // 25 | module MapData = 26 | open System.Collections.Generic 27 | 28 | // 29 | let createSequential size = 30 | Array.init size <| fun i -> 31 | KeyValuePair<_,_> (i, string i) 32 | 33 | // 34 | let createRandom size = 35 | // Create a hash set. We'll use this to check each randomly-created data point 36 | // to determine if we've already seen it; if not, we add the value (and it's string representation) 37 | // to the list of data to use for the map test. 38 | let seen = HashSet<_> () 39 | let mutable data = ResizeArray<_> () 40 | let rng = Random () 41 | 42 | while seen.Count < size do 43 | let currentElement = rng.Next () 44 | 45 | if seen.Add currentElement then 46 | data.Add (KeyValuePair<_,_> (currentElement, string currentElement)) 47 | 48 | data.ToArray () 49 | 50 | 51 | /// Benchmark of lookup (find) performance of maps / dictionaries 52 | /// using integer keys. 53 | //[] 54 | type MapFindIntKey () = 55 | let mutable mapData = Array.empty 56 | let mutable fsharpMap = Map.empty 57 | let mutable intMap = IntMap.empty 58 | let mutable dictionary = dict Array.empty 59 | 60 | [] 61 | member val public Randomized = false with get, set 62 | 63 | [] 64 | member val public DictSize = 0 with get, set 65 | 66 | [] 67 | member self.Setup () : unit = 68 | // Create data for the test. 69 | mapData <- 70 | if self.Randomized then 71 | MapData.createRandom self.DictSize 72 | else 73 | MapData.createSequential self.DictSize 74 | 75 | // Create the data structures using the generated data. 76 | fsharpMap <- 77 | (Map.empty, mapData) 78 | ||> Array.fold (fun map (KeyValue (k, v)) -> 79 | Map.add k v map) 80 | 81 | intMap <- 82 | (IntMap.empty, mapData) 83 | ||> Array.fold (fun map (KeyValue (k, v)) -> 84 | IntMap.add k v map) 85 | 86 | dictionary <- 87 | mapData 88 | |> Seq.map (fun (KeyValue (k, v)) -> k, v) 89 | |> dict 90 | 91 | [] 92 | member __.FSharpMap () : unit = 93 | // Iterate through all keys in the map data, looking each one up 94 | // in the map (to fetch the associated value). 95 | for kvp in mapData do 96 | Map.find kvp.Key fsharpMap |> ignore 97 | 98 | [] 99 | member __.IntMap () : unit = 100 | // Iterate through all keys in the map data, looking each one up 101 | // in the map (to fetch the associated value). 102 | for kvp in mapData do 103 | IntMap.find kvp.Key intMap |> ignore 104 | 105 | [] 106 | member __.Dictionary () : unit = 107 | // Iterate through all keys in the map data, looking each one up 108 | // in the dictionary (to fetch the associated value). 109 | for kvp in mapData do 110 | dictionary.[kvp.Key] |> ignore 111 | 112 | 113 | /// Benchmark comparing creation time of maps / dictionaries 114 | /// using integer keys. 115 | //[] 116 | type MapCreateIntKey () = 117 | let mutable mapData = Array.empty 118 | 119 | [] 120 | member val public Randomized = false with get, set 121 | 122 | [] 123 | member val public DictSize = 0 with get, set 124 | 125 | [] 126 | member self.Setup () : unit = 127 | // Create data for the test. 128 | mapData <- 129 | if self.Randomized then 130 | MapData.createRandom self.DictSize 131 | else 132 | MapData.createSequential self.DictSize 133 | 134 | [] 135 | member __.FSharpMap () : unit = 136 | // Iterate through all keys in the map data, adding each one to the map. 137 | let mutable map = Map.empty 138 | for kvp in mapData do 139 | map <- Map.add kvp.Key kvp.Value map 140 | 141 | [] 142 | member __.IntMap () : unit = 143 | // Iterate through all keys in the map data, adding each one to the map. 144 | let mutable map = IntMap.empty 145 | for kvp in mapData do 146 | map <- IntMap.add kvp.Key kvp.Value map 147 | 148 | [] 149 | member __.Dictionary () : unit = 150 | // Iterate through all keys in the map data, adding each one to the map. 151 | let dict = System.Collections.Generic.Dictionary<_,_>() 152 | for kvp in mapData do 153 | dict.Add(kvp.Key, kvp.Value) 154 | -------------------------------------------------------------------------------- /ExtCore.Benchmarks/Collections.IntSet.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2018 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Benchmarks for the ExtCore.Collections.IntSet type and module. 20 | namespace Benchmarks.ExtCore.Collections.IntSet 21 | 22 | open System 23 | open System.Collections 24 | open System.Collections.Generic 25 | open BenchmarkDotNet.Attributes 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ExtCore.Benchmarks/ExtCore.Benchmarks.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.0;net46 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ExtCore.Benchmarks/Program.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2018 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace Benchmarks.ExtCore 20 | 21 | open BenchmarkDotNet 22 | 23 | 24 | module Program = 25 | open BenchmarkDotNet.Running 26 | 27 | let defaultSwitch = 28 | [| typeof; 29 | typeof; 30 | |] |> BenchmarkSwitcher 31 | 32 | // 33 | [] 34 | let main args = 35 | let summaries = defaultSwitch.Run args 36 | 37 | 0 38 | -------------------------------------------------------------------------------- /ExtCore.Tests/Args.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the modules in the ExtCore.Args namespace. 20 | module Tests.ExtCore.Args 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.AsyncSeq.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the ExtCore.Collections.AsyncSeq module. 20 | module Tests.ExtCore.Collections.AsyncSeq 21 | 22 | open NUnit.Framework 23 | 24 | 25 | [] 26 | let empty () = 27 | Assert.Ignore "Test not yet implemented." 28 | 29 | [] 30 | let singleton () = 31 | Assert.Ignore "Test not yet implemented." 32 | 33 | [] 34 | let firstOrDefault () = 35 | Assert.Ignore "Test not yet implemented." 36 | 37 | [] 38 | let lastOrDefault () = 39 | Assert.Ignore "Test not yet implemented." 40 | 41 | [] 42 | let append () = 43 | Assert.Ignore "Test not yet implemented." 44 | 45 | [] 46 | let collect () = 47 | Assert.Ignore "Test not yet implemented." 48 | 49 | [] 50 | let map () = 51 | Assert.Ignore "Test not yet implemented." 52 | 53 | [] 54 | let choose () = 55 | Assert.Ignore "Test not yet implemented." 56 | 57 | [] 58 | let filter () = 59 | Assert.Ignore "Test not yet implemented." 60 | 61 | [] 62 | let scan () = 63 | Assert.Ignore "Test not yet implemented." 64 | 65 | [] 66 | let iter () = 67 | Assert.Ignore "Test not yet implemented." 68 | 69 | [] 70 | let fold () = 71 | Assert.Ignore "Test not yet implemented." 72 | 73 | [] 74 | let pairwise () = 75 | Assert.Ignore "Test not yet implemented." 76 | 77 | [] 78 | let zip () = 79 | Assert.Ignore "Test not yet implemented." 80 | 81 | [] 82 | let zip3 () = 83 | Assert.Ignore "Test not yet implemented." 84 | 85 | [] 86 | let take () = 87 | Assert.Ignore "Test not yet implemented." 88 | 89 | [] 90 | let takeWhile () = 91 | Assert.Ignore "Test not yet implemented." 92 | 93 | [] 94 | let skip () = 95 | Assert.Ignore "Test not yet implemented." 96 | 97 | [] 98 | let skipWhile () = 99 | Assert.Ignore "Test not yet implemented." 100 | 101 | [] 102 | let cache () = 103 | Assert.Ignore "Test not yet implemented." 104 | 105 | [] 106 | let ofSeq () = 107 | Assert.Ignore "Test not yet implemented." 108 | 109 | [] 110 | let toSeq () = 111 | Assert.Ignore "Test not yet implemented." 112 | 113 | [] 114 | let ofObservableBuffered () = 115 | Assert.Ignore "Test not yet implemented." 116 | 117 | [] 118 | let ofObservable () = 119 | Assert.Ignore "Test not yet implemented." 120 | 121 | [] 122 | let toObservable () = 123 | Assert.Ignore "Test not yet implemented." 124 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Dict.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.Dict module. 20 | module Tests.ExtCore.Collections.Dict 21 | 22 | open System 23 | open System.Collections.Generic 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | [] 29 | let keys () : unit = 30 | Assert.Ignore "Test not yet implemented." 31 | 32 | [] 33 | let values () : unit = 34 | Assert.Ignore "Test not yet implemented." 35 | 36 | [] 37 | let isEmpty () : unit = 38 | Assert.Ignore "Test not yet implemented." 39 | 40 | [] 41 | let count () : unit = 42 | Assert.Ignore "Test not yet implemented." 43 | 44 | [] 45 | let createMutable () : unit = 46 | Assert.Ignore "Test not yet implemented." 47 | 48 | [] 49 | let containsKey () : unit = 50 | Assert.Ignore "Test not yet implemented." 51 | 52 | [] 53 | let add () : unit = 54 | Assert.Ignore "Test not yet implemented." 55 | 56 | [] 57 | let remove () : unit = 58 | Assert.Ignore "Test not yet implemented." 59 | 60 | [] 61 | let find () : unit = 62 | Assert.Ignore "Test not yet implemented." 63 | 64 | [] 65 | let tryFind () : unit = 66 | Assert.Ignore "Test not yet implemented." 67 | 68 | [] 69 | let update () : unit = 70 | Assert.Ignore "Test not yet implemented." 71 | 72 | [] 73 | let updateOrAdd () : unit = 74 | Assert.Ignore "Test not yet implemented." 75 | 76 | [] 77 | let tryPick () : unit = 78 | Assert.Ignore "Test not yet implemented." 79 | 80 | [] 81 | let pick () : unit = 82 | Assert.Ignore "Test not yet implemented." 83 | 84 | [] 85 | let toSeq () : unit = 86 | Assert.Ignore "Test not yet implemented." 87 | 88 | [] 89 | let iter () : unit = 90 | Assert.Ignore "Test not yet implemented." 91 | 92 | [] 93 | let filter () : unit = 94 | Assert.Ignore "Test not yet implemented." 95 | 96 | [] 97 | let map () : unit = 98 | Assert.Ignore "Test not yet implemented." 99 | 100 | [] 101 | let choose () : unit = 102 | Assert.Ignore "Test not yet implemented." 103 | 104 | [] 105 | let fold () : unit = 106 | Assert.Ignore "Test not yet implemented." 107 | 108 | [] 109 | let partition () : unit = 110 | Assert.Ignore "Test not yet implemented." 111 | 112 | [] 113 | let readonly () : unit = 114 | Assert.Ignore "Test not yet implemented." 115 | 116 | 117 | module Safe = 118 | [] 119 | let tryFind () : unit = 120 | Assert.Ignore "Test not yet implemented." 121 | 122 | [] 123 | let find () : unit = 124 | Assert.Ignore "Test not yet implemented." 125 | 126 | [] 127 | let add () : unit = 128 | Assert.Ignore "Test not yet implemented." 129 | 130 | [] 131 | let update () : unit = 132 | Assert.Ignore "Test not yet implemented." 133 | 134 | [] 135 | let remove () : unit = 136 | Assert.Ignore "Test not yet implemented." 137 | 138 | [] 139 | let updateOrAdd () : unit = 140 | Assert.Ignore "Test not yet implemented." 141 | 142 | [] 143 | let immutable () : unit = 144 | Assert.Ignore "Test not yet implemented." 145 | 146 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.ListZipper.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.ListZipper type and module. 20 | module Tests.ExtCore.Collections.ListZipper 21 | 22 | open NUnit.Framework 23 | 24 | 25 | [] 26 | let isEmpty () : unit = 27 | Assert.Ignore "Test not yet implemented." 28 | 29 | [] 30 | let atStart () : unit = 31 | Assert.Ignore "Test not yet implemented." 32 | 33 | [] 34 | let atEnd () : unit = 35 | Assert.Ignore "Test not yet implemented." 36 | 37 | [] 38 | let context () : unit = 39 | Assert.Ignore "Test not yet implemented." 40 | 41 | [] 42 | let current () : unit = 43 | Assert.Ignore "Test not yet implemented." 44 | 45 | [] 46 | let prev () : unit = 47 | Assert.Ignore "Test not yet implemented." 48 | 49 | [] 50 | let moveBack () : unit = 51 | Assert.Ignore "Test not yet implemented." 52 | 53 | [] 54 | let moveNext () : unit = 55 | Assert.Ignore "Test not yet implemented." 56 | 57 | [] 58 | let moveStart () : unit = 59 | Assert.Ignore "Test not yet implemented." 60 | 61 | [] 62 | let moveEnd () : unit = 63 | Assert.Ignore "Test not yet implemented." 64 | 65 | [] 66 | let remove () : unit = 67 | Assert.Ignore "Test not yet implemented." 68 | 69 | [] 70 | let insert () : unit = 71 | Assert.Ignore "Test not yet implemented." 72 | 73 | [] 74 | let update () : unit = 75 | Assert.Ignore "Test not yet implemented." 76 | 77 | [] 78 | let ofList () : unit = 79 | Assert.Ignore "Test not yet implemented." 80 | 81 | [] 82 | let toList () : unit = 83 | Assert.Ignore "Test not yet implemented." 84 | 85 | 86 | 87 | open FsCheck 88 | 89 | (* TODO : Implement FsCheck-based tests for ListZipper. *) 90 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.LongBimap.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2005-2009 Microsoft Corporation 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | /// Unit tests for the ExtCore.Collections.LongBimap type and module. 21 | module Tests.ExtCore.Collections.LongBimap 22 | 23 | open System 24 | open System.Collections 25 | open System.Collections.Generic 26 | open NUnit.Framework 27 | 28 | 29 | [] 30 | let dummy () : unit = 31 | Assert.Ignore "Test not yet implemented." 32 | 33 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Multimap.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2014 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.Multimap type and module. 20 | module Tests.ExtCore.Collections.Multimap 21 | 22 | open System 23 | open System.Collections 24 | open System.Collections.Generic 25 | open NUnit.Framework 26 | 27 | 28 | // 29 | [] 30 | let isEmpty () = 31 | Assert.Ignore "Test not yet implemented." 32 | 33 | // 34 | [] 35 | let singleton () = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | // 39 | [] 40 | let add () = 41 | Assert.Ignore "Test not yet implemented." 42 | 43 | // 44 | [] 45 | let remove () = 46 | Assert.Ignore "Test not yet implemented." 47 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Multiset.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2014 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.Multiset type and module. 20 | module Tests.ExtCore.Collections.Multiset 21 | 22 | open System 23 | open System.Collections 24 | open System.Collections.Generic 25 | open NUnit.Framework 26 | 27 | 28 | // 29 | [] 30 | let isEmpty () = 31 | Assert.Ignore "Test not yet implemented." 32 | 33 | // 34 | [] 35 | let count () = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | // 39 | [] 40 | let countDistinct () = 41 | Assert.Ignore "Test not yet implemented." 42 | 43 | // 44 | [] 45 | let contains () = 46 | Assert.Ignore "Test not yet implemented." 47 | 48 | // 49 | [] 50 | let card () = 51 | Assert.Ignore "Test not yet implemented." 52 | 53 | // 54 | [] 55 | let singleton () = 56 | Assert.Ignore "Test not yet implemented." 57 | 58 | // 59 | [] 60 | let add () = 61 | Assert.Ignore "Test not yet implemented." 62 | 63 | // 64 | [] 65 | let addMany () = 66 | Assert.Ignore "Test not yet implemented." 67 | 68 | // 69 | [] 70 | let remove () = 71 | Assert.Ignore "Test not yet implemented." 72 | 73 | // 74 | [] 75 | let removeMany () = 76 | Assert.Ignore "Test not yet implemented." 77 | 78 | // 79 | [] 80 | let removeAll () = 81 | Assert.Ignore "Test not yet implemented." 82 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.PriorityQueue.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.PriorityQueue type and module. 20 | module Tests.ExtCore.Collections.PriorityQueue 21 | 22 | open NUnit.Framework 23 | //open FsCheck 24 | 25 | 26 | (* TODO : Implement tests for ExtCore.Collections.PriorityQueue. *) 27 | 28 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Queue.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.Queue type and module. 20 | namespace Tests.ExtCore.Collections 21 | 22 | open NUnit.Framework 23 | //open FsCheck 24 | 25 | 26 | module QueueType = 27 | [] 28 | let IsEmpty () : unit = 29 | Assert.Ignore "Test not yet implemented." 30 | 31 | [] 32 | let GetLength () : unit = 33 | Assert.Ignore "Test not yet implemented." 34 | 35 | [] 36 | let Dequeue () : unit = 37 | Assert.Ignore "Test not yet implemented." 38 | 39 | [] 40 | let Enqueue () : unit = 41 | Assert.Ignore "Test not yet implemented." 42 | 43 | [] 44 | let EnqueueFront () : unit = 45 | Assert.Ignore "Test not yet implemented." 46 | 47 | [] 48 | let OfSeq () : unit = 49 | Assert.Ignore "Test not yet implemented." 50 | 51 | [] 52 | let OfList () : unit = 53 | Assert.Ignore "Test not yet implemented." 54 | 55 | [] 56 | let OfArray () : unit = 57 | Assert.Ignore "Test not yet implemented." 58 | 59 | [] 60 | let OfVector () : unit = 61 | Assert.Ignore "Test not yet implemented." 62 | 63 | [] 64 | let ToSeq () : unit = 65 | Assert.Ignore "Test not yet implemented." 66 | 67 | [] 68 | let ToList () : unit = 69 | Assert.Ignore "Test not yet implemented." 70 | 71 | [] 72 | let ToArray () : unit = 73 | Assert.Ignore "Test not yet implemented." 74 | 75 | [] 76 | let ToVector () : unit = 77 | Assert.Ignore "Test not yet implemented." 78 | 79 | [] 80 | let ``IEnumerable.GetEnumerator()`` () : unit = 81 | Assert.Ignore "Test not yet implemented." 82 | 83 | [] 84 | let ``IEnumerable<'T>.GetEnumerator()`` () : unit = 85 | Assert.Ignore "Test not yet implemented." 86 | 87 | 88 | module QueueModule = 89 | [] 90 | let isEmpty () : unit = 91 | Queue.empty 92 | |> Queue.isEmpty 93 | |> assertTrue 94 | 95 | Queue.empty 96 | |> Queue.enqueue "Hello" 97 | |> Queue.enqueue "World!" 98 | |> Queue.isEmpty 99 | |> assertFalse 100 | 101 | [] 102 | let length () : unit = 103 | Queue.empty 104 | |> Queue.length 105 | |> assertEqual 0 106 | 107 | Queue.empty 108 | |> Queue.enqueue "foo" 109 | |> Queue.enqueue "bar" 110 | |> Queue.enqueue "baz" 111 | |> Queue.length 112 | |> assertEqual 3 113 | 114 | [] 115 | let enqueue () : unit = 116 | Queue.empty 117 | |> Queue.enqueue "Hello" 118 | |> Queue.toArray 119 | |> assertEqual 120 | [| "Hello" |] 121 | 122 | [| "foo"; "bar"; "baz"; |] 123 | |> Queue.ofArray 124 | |> Queue.enqueue "cdr" 125 | |> Queue.enqueue "car" 126 | |> Queue.enqueue "bar" 127 | |> Queue.enqueue "bar" 128 | |> Queue.toArray 129 | |> assertEqual 130 | [| "foo"; "bar"; "baz"; "cdr"; "car"; "bar"; "bar"; |] 131 | 132 | // Test case for checking that the Queue is persistent as expected. 133 | do 134 | let queue = Queue.ofArray [| "foo"; "bar"; "baz"; |] 135 | 136 | queue 137 | |> Queue.enqueue "Hello" 138 | |> Queue.enqueue "World" 139 | |> Queue.toArray 140 | |> assertEqual 141 | [| "foo"; "bar"; "baz"; "Hello"; "World"; |] 142 | 143 | queue 144 | |> Queue.enqueue "cdr" 145 | |> Queue.enqueue "car" 146 | |> Queue.toArray 147 | |> assertEqual 148 | [| "foo"; "bar"; "baz"; "cdr"; "car"; |] 149 | 150 | [] 151 | let enqueueFront () : unit = 152 | Queue.empty 153 | |> Queue.enqueueFront "Hello" 154 | |> Queue.toArray 155 | |> assertEqual 156 | [| "Hello" |] 157 | 158 | Queue.empty 159 | |> Queue.enqueue "foo" 160 | |> Queue.enqueue "bar" 161 | |> Queue.enqueueFront "baz" 162 | |> Queue.enqueue "cdr" 163 | |> Queue.enqueueFront "car" 164 | |> Queue.toArray 165 | |> assertEqual 166 | [| "car"; "baz"; "foo"; "bar"; "cdr"; |] 167 | 168 | // Test case for checking that the Queue is persistent as expected. 169 | do 170 | let queue = Queue.ofArray [| "foo"; "bar"; "baz"; |] 171 | 172 | queue 173 | |> Queue.enqueueFront "Hello" 174 | |> Queue.enqueueFront "World" 175 | |> Queue.toArray 176 | |> assertEqual 177 | [| "World"; "Hello"; "foo"; "bar"; "baz"; |] 178 | 179 | queue 180 | |> Queue.enqueueFront "cdr" 181 | |> Queue.enqueueFront "car" 182 | |> Queue.toArray 183 | |> assertEqual 184 | [| "car"; "cdr"; "foo"; "bar"; "baz"; |] 185 | 186 | [] 187 | let dequeue () : unit = 188 | do 189 | let queue = Queue.ofArray [| "car"; "baz"; "foo"; "bar"; "cdr"; |] 190 | 191 | let result, queue = Queue.dequeue queue 192 | result |> assertEqual "car" 193 | Queue.length queue |> assertEqual 4 194 | 195 | let result, queue = Queue.dequeue queue 196 | result |> assertEqual "baz" 197 | Queue.length queue |> assertEqual 3 198 | 199 | let result, queue = Queue.dequeue queue 200 | result |> assertEqual "foo" 201 | Queue.length queue |> assertEqual 2 202 | 203 | let result, queue = Queue.dequeue queue 204 | result |> assertEqual "bar" 205 | Queue.length queue |> assertEqual 1 206 | 207 | let result, queue = Queue.dequeue queue 208 | result |> assertEqual "cdr" 209 | Queue.length queue |> assertEqual 0 210 | 211 | // Test case for checking that the Queue is persistent as expected. 212 | do 213 | let queue = Queue.ofArray [| "car"; "baz"; "foo"; "bar"; "cdr"; |] 214 | 215 | // Run a simple dequeue test. 216 | let result, queue = Queue.dequeue queue 217 | result |> assertEqual "car" 218 | Queue.length queue |> assertEqual 4 219 | 220 | let result, queue = Queue.dequeue queue 221 | result |> assertEqual "baz" 222 | Queue.length queue |> assertEqual 3 223 | 224 | // Change to queue' here, so we can use the "partial" queue later. 225 | let result, queue' = Queue.dequeue queue 226 | result |> assertEqual "foo" 227 | Queue.length queue' |> assertEqual 2 228 | 229 | let result, queue' = Queue.dequeue queue' 230 | result |> assertEqual "bar" 231 | Queue.length queue' |> assertEqual 1 232 | 233 | let result, queue' = Queue.dequeue queue' 234 | result |> assertEqual "cdr" 235 | Queue.length queue' |> assertEqual 0 236 | 237 | // Now re-run the test for the last few elements using the partial queue. 238 | let result, queue = Queue.dequeue queue 239 | result |> assertEqual "foo" 240 | Queue.length queue |> assertEqual 2 241 | 242 | let result, queue = Queue.dequeue queue 243 | result |> assertEqual "bar" 244 | Queue.length queue |> assertEqual 1 245 | 246 | let result, queue = Queue.dequeue queue 247 | result |> assertEqual "cdr" 248 | Queue.length queue |> assertEqual 0 249 | 250 | [] 251 | let ``dequeue raises exn when queue is empty`` () : unit = 252 | Assert.Throws(fun () -> 253 | Queue.empty 254 | |> Queue.dequeue 255 | |> ignore) |> ignore 256 | 257 | [] 258 | let ofList () : unit = 259 | List.empty 260 | |> Queue.ofList 261 | |> Queue.isEmpty 262 | |> assertTrue 263 | 264 | ["foo"; "bar"; "baz"; "cdr"; "car"] 265 | |> Queue.ofList 266 | |> Queue.toSeq 267 | |> Seq.toArray 268 | |> assertEqual 269 | [| "foo"; "bar"; "baz"; "cdr"; "car"; |] 270 | 271 | [] 272 | let ofArray () : unit = 273 | List.empty 274 | |> Queue.ofList 275 | |> Queue.isEmpty 276 | |> assertTrue 277 | 278 | [| "foo"; "bar"; "baz"; "cdr"; "car"; |] 279 | |> Queue.ofArray 280 | |> Queue.toSeq 281 | |> Seq.toArray 282 | |> assertEqual 283 | [| "foo"; "bar"; "baz"; "cdr"; "car"; |] 284 | 285 | [] 286 | let toSeq () : unit = 287 | Queue.empty 288 | |> Queue.toSeq 289 | |> Seq.isEmpty 290 | |> assertTrue 291 | 292 | Queue.empty 293 | |> Queue.enqueue "foo" 294 | |> Queue.enqueue "bar" 295 | |> Queue.enqueue "baz" 296 | |> Queue.dequeue 297 | |> snd 298 | |> Queue.enqueue "cdr" 299 | |> Queue.enqueue "car" 300 | |> Queue.toSeq 301 | |> Seq.toArray 302 | |> assertEqual 303 | [| "bar"; "baz"; "cdr"; "car"; |] 304 | 305 | [] 306 | let toList () : unit = 307 | Queue.empty 308 | |> Queue.toList 309 | |> List.isEmpty 310 | |> assertTrue 311 | 312 | Queue.empty 313 | |> Queue.enqueue "foo" 314 | |> Queue.enqueue "bar" 315 | |> Queue.enqueue "baz" 316 | |> Queue.dequeue 317 | |> snd 318 | |> Queue.enqueue "cdr" 319 | |> Queue.enqueue "car" 320 | |> Queue.toList 321 | |> assertEqual 322 | ["bar"; "baz"; "cdr"; "car"] 323 | 324 | [] 325 | let toArray () : unit = 326 | Queue.empty 327 | |> Queue.toArray 328 | |> Array.isEmpty 329 | |> assertTrue 330 | 331 | Queue.empty 332 | |> Queue.enqueue "foo" 333 | |> Queue.enqueue "bar" 334 | |> Queue.enqueue "baz" 335 | |> Queue.dequeue 336 | |> snd 337 | |> Queue.enqueue "cdr" 338 | |> Queue.enqueue "car" 339 | |> Queue.toArray 340 | |> assertEqual 341 | [| "bar"; "baz"; "cdr"; "car"; |] 342 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Range.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the ExtCore.Collections.Range module. 20 | module Tests.ExtCore.Collections.Range 21 | 22 | open NUnit.Framework 23 | 24 | 25 | [] 26 | let iter () : unit = 27 | do 28 | // Test case for an inverted range (this should 29 | // be treated just like an empty range). 30 | let elements = ResizeArray () 31 | 32 | (5, 2) 33 | ||> Range.iter (fun x -> 34 | String.replicate x "A" 35 | |> elements.Add) 36 | 37 | ResizeArray.isEmpty elements 38 | |> assertTrue 39 | 40 | do 41 | // Test case for a single-element range. 42 | let elements = ResizeArray () 43 | 44 | (4, 4) 45 | ||> Range.iter (fun x -> 46 | String.replicate x "A" 47 | |> elements.Add) 48 | 49 | ResizeArray.toArray elements 50 | |> Collection.assertEqual [| "AAAA"; |] 51 | 52 | do 53 | // Sample usage test case. 54 | let elements = ResizeArray () 55 | 56 | (2, 7) 57 | ||> Range.iter (fun x -> 58 | String.replicate x "A" 59 | |> elements.Add) 60 | 61 | ResizeArray.toArray elements 62 | |> Collection.assertEqual 63 | [| "AA"; "AAA"; "AAAA"; "AAAAA"; "AAAAAA"; "AAAAAAA"; |] 64 | 65 | [] 66 | let fold () : unit = 67 | /// The set of prime numbers less than 40. 68 | let primes = 69 | Set.ofArray [| 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; |] 70 | 71 | do 72 | // Test case for an inverted range (this should 73 | // be treated just like an empty range). 74 | (5, 2, 1L) 75 | |||> Range.fold (fun checksum x -> 76 | if Set.contains x primes then 77 | checksum * int64 x 78 | else 79 | checksum + int64 x) 80 | |> assertEqual 1L 81 | 82 | do 83 | // Test cases for a single-element range. 84 | (6, 6, 1L) 85 | |||> Range.fold (fun checksum x -> 86 | if Set.contains x primes then 87 | checksum * int64 x 88 | else 89 | checksum + int64 x) 90 | |> assertEqual 7L 91 | 92 | (5, 5, 1L) 93 | |||> Range.fold (fun checksum x -> 94 | if Set.contains x primes then 95 | checksum * int64 x 96 | else 97 | checksum + int64 x) 98 | |> assertEqual 5L 99 | 100 | do 101 | // Sample usage test cases. 102 | (2, 7, 1L) 103 | |||> Range.fold (fun checksum x -> 104 | if Set.contains x primes then 105 | checksum * int64 x 106 | else 107 | checksum + int64 x) 108 | |> assertEqual 392L 109 | 110 | (20, 30, 1L) 111 | |||> Range.fold (fun checksum x -> 112 | if Set.contains x primes then 113 | checksum * int64 x 114 | else 115 | checksum + int64 x) 116 | |> assertEqual 46488L 117 | 118 | [] 119 | let foldBack () : unit = 120 | /// The set of prime numbers less than 40. 121 | let primes = 122 | Set.ofArray [| 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; |] 123 | 124 | do 125 | // Test case for an inverted range (this should 126 | // be treated just like an empty range). 127 | (5, 2, 1L) 128 | |||> Range.foldBack (fun x checksum -> 129 | if Set.contains x primes then 130 | checksum * int64 x 131 | else 132 | checksum + int64 x) 133 | |> assertEqual 1L 134 | 135 | do 136 | // Test cases for a single-element range. 137 | (6, 6, 1L) 138 | |||> Range.foldBack (fun x checksum -> 139 | if Set.contains x primes then 140 | checksum * int64 x 141 | else 142 | checksum + int64 x) 143 | |> assertEqual 7L 144 | 145 | (5, 5, 1L) 146 | |||> Range.foldBack (fun x checksum -> 147 | if Set.contains x primes then 148 | checksum * int64 x 149 | else 150 | checksum + int64 x) 151 | |> assertEqual 5L 152 | 153 | do 154 | // Sample usage test cases. 155 | (2, 7, 1L) 156 | |||> Range.foldBack (fun x checksum -> 157 | if Set.contains x primes then 158 | checksum * int64 x 159 | else 160 | checksum + int64 x) 161 | |> assertEqual 414L 162 | 163 | (20, 30, 1L) 164 | |||> Range.foldBack (fun x checksum -> 165 | if Set.contains x primes then 166 | checksum * int64 x 167 | else 168 | checksum + int64 x) 169 | |> assertEqual 23730L 170 | 171 | [] 172 | let exists () : unit = 173 | /// The set of prime numbers less than 40. 174 | let primes = 175 | Set.ofArray [| 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; |] 176 | 177 | do 178 | // Test case for an inverted range (this should 179 | // be treated just like an empty range). 180 | (5, 2) 181 | ||> Range.exists (fun x -> 182 | Set.contains x primes) 183 | |> assertFalse 184 | 185 | do 186 | // Test cases for a single-element range. 187 | (4, 4) 188 | ||> Range.exists (fun x -> 189 | Set.contains x primes) 190 | |> assertFalse 191 | 192 | (5, 5) 193 | ||> Range.exists (fun x -> 194 | Set.contains x primes) 195 | |> assertTrue 196 | 197 | do 198 | // Sample usage test case. 199 | (2, 7) 200 | ||> Range.exists (fun x -> 201 | Set.contains x primes) 202 | |> assertTrue 203 | 204 | [] 205 | let forall () : unit = 206 | /// The set of prime numbers less than 40. 207 | let primes = 208 | Set.ofArray [| 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; |] 209 | 210 | do 211 | // Test case for an inverted range (this should 212 | // be treated just like an empty range). 213 | (5, 2) 214 | ||> Range.forall (fun x -> 215 | not <| Set.contains x primes) 216 | |> assertTrue 217 | 218 | do 219 | // Test cases for a single-element range. 220 | (4, 4) 221 | ||> Range.forall (fun x -> 222 | not <| Set.contains x primes) 223 | |> assertTrue 224 | 225 | (5, 5) 226 | ||> Range.forall (fun x -> 227 | not <| Set.contains x primes) 228 | |> assertFalse 229 | 230 | do 231 | // Sample usage test cases. 232 | (14, 18) 233 | ||> Range.forall (fun x -> 234 | not <| Set.contains x primes) 235 | |> assertFalse 236 | 237 | (24, 28) 238 | ||> Range.forall (fun x -> 239 | not <| Set.contains x primes) 240 | |> assertTrue 241 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.ResizeArray.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2005-2009 Microsoft Corporation 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | (* NOTE : This file has been modified from it's original form in the F# PowerPack. *) 21 | 22 | /// Unit tests for the ExtCore.Collections.ResizeArray module. 23 | module Tests.ExtCore.Collections.ResizeArray 24 | 25 | open NUnit.Framework 26 | //open FsCheck 27 | 28 | 29 | // TODO : Remove this ASAP, replacing any uses with direct calls to Assert.IsTrue. 30 | let private test msg (condition: bool) = 31 | Assert.IsTrue (condition, sprintf "MiniTest '%s'" msg) 32 | 33 | 34 | [] 35 | let ``Basic Tests`` () : unit = 36 | let ra = ResizeArray.ofList 37 | let (=?) a b = ResizeArray.toList a = b 38 | 39 | test "ra_exists2_a" <| ResizeArray.exists2 (=) 40 | (ra [1; 2; 3; 4; 5; 6]) 41 | (ra [2; 3; 4; 5; 6; 6]) 42 | 43 | test "exists2_b" <| not (ResizeArray.exists2 (=) 44 | (ra [1; 2; 3; 4; 5; 6]) 45 | (ra [2; 3; 4; 5; 6; 7])) 46 | 47 | test "ra_findIndex_a" 48 | (ResizeArray.findIndex (fun i -> i >= 4) (ra [0..10]) = 4) 49 | 50 | test "ra_findIndex_b" 51 | (try ResizeArray.findIndex (fun i -> i >= 20) (ra [0..10]) |> ignore; false 52 | with _ -> true) 53 | 54 | test "ra_find_indexi_a" 55 | (ResizeArray.findIndexi (=) (ra [1; 2; 3; 3; 2; 1]) = 3) 56 | 57 | test "ra_find_indexi_b" 58 | (try ResizeArray.findIndexi (=) (ra [1..10]) |> ignore; false 59 | with _ -> true) 60 | 61 | test "ra_forall2_a" 62 | (ResizeArray.forall2 (=) (ra [1..10]) (ra [1..10])) 63 | 64 | test "ra_forall2_b" <| not 65 | (ResizeArray.forall2 (=) (ra [1;2;3;4;5]) (ra [1;2;3;0;5])) 66 | 67 | test "ra_isEmpty_a" 68 | (ResizeArray.isEmpty (ra [])) 69 | 70 | test "ra_isEmpty_b" <| not 71 | (ResizeArray.isEmpty (ra [1; 2])) 72 | 73 | test "ra_mapi2" 74 | (ResizeArray.mapi2 (fun i j k -> i+j+k) (ra [1..10]) (ra [1..10]) =? [2..+3..29]) 75 | 76 | test "ra_mapi2_b" 77 | (try ResizeArray.mapi2 (fun i j k -> i+j+k) (ra []) (ra [1..10]) |> ignore; false 78 | with _ -> true) 79 | 80 | let c = ref 0 81 | ResizeArray.iteri2 (fun i j k -> c := !c+i+j+k) (ra [1;2;3]) (ra [10;20;30]) 82 | test "ra_iteri2" (!c = 6+60+3) 83 | 84 | test "ra_singleton" 85 | (ResizeArray.singleton 42 =? [42]) 86 | 87 | test "ra_zip" 88 | (ResizeArray.zip (ra [1..10]) (ra [1..10]) =? [for i in 1..10 -> i, i]) 89 | 90 | let unzip1, unzip2 = ResizeArray.unzip <| ra [for i in 1..10 -> i, i+1] 91 | test "ra_unzip" (unzip1 =? [1..10] && unzip2 =? [2..11]) 92 | 93 | test "ra_reduce_left" 94 | (ResizeArray.reduce (+) (ra [2;2;2;2]) = 8) 95 | 96 | test "ra_reduce_right" 97 | (ResizeArray.reduceBack (+) (ra [2;2;2;2]) = 8) 98 | 99 | test "ra_fold2" 100 | (ResizeArray.fold2 (fun i j k -> i+j+k) 100 (ra [1;2;3]) (ra [1;2;3]) = 112) 101 | 102 | test "ra_fold2_b" 103 | (ResizeArray.fold2 (fun i j k -> i-j-k) 100 (ra [1;2;3]) (ra [1;2;3]) = 100-12) 104 | 105 | test "ra_foldBack2" 106 | (ResizeArray.foldBack2 (fun i j k -> i+j+k) (ra [1;2;3]) (ra [1;2;3]) 100 = 112) 107 | 108 | test "ra_foldBack2_b" 109 | (ResizeArray.foldBack2 (fun i j k -> k-i-j) (ra [1;2;3]) (ra [1;2;3]) 100 = 100-12) 110 | 111 | test "ra_scan" 112 | (ResizeArray.scan (+) 0 (ra [1..5]) =? [0; 1; 3; 6; 10; 15]) 113 | 114 | test "ra_scanBack" 115 | (ResizeArray.scanBack (+) (ra [1..5]) 0 =? [15; 14; 12; 9; 5; 0]) 116 | 117 | test "ra_tryfind_index" 118 | (ResizeArray.tryFindIndex (fun x -> x = 4) (ra [0..10]) = Some 4) 119 | 120 | test "ra_tryfind_index_b" 121 | (ResizeArray.tryFindIndex (fun x -> x = 42) (ra [0..10]) = None) 122 | 123 | test "ra_tryfind_indexi" 124 | (ResizeArray.tryFindIndexi (=) (ra [1;2;3;4;4;3;2;1]) = Some 4) 125 | 126 | test "ra_tryfind_indexi_b" 127 | (ResizeArray.tryFindIndexi (=) (ra [1..10]) = None) 128 | 129 | c := -1 130 | ResizeArray.iter (fun x -> incr c; test "ra_iter" (x = !c)) (ra [0..100]) 131 | test "ra_iter" (!c = 100) 132 | 133 | test "ra_map" 134 | (ra [1..100] |> ResizeArray.map ((+) 1) =? [2..101]) 135 | 136 | test "ra_mapi" 137 | (ra [0..100] |> ResizeArray.mapi (+) =? [0..+2..200]) 138 | 139 | c := -1 140 | ResizeArray.iteri (fun i x -> incr c; test "ra_iteri" (x = !c && i = !c)) (ra [0..100]) 141 | test "ra_iteri" (!c = 100) 142 | 143 | test "ra_exists" 144 | (ra [1..100] |> ResizeArray.exists ((=) 50)) 145 | 146 | test "ra_exists b" <| not 147 | (ra [1..100] |> ResizeArray.exists ((=) 150)) 148 | 149 | test "ra_forall" 150 | (ra [1..100] |> ResizeArray.forall (fun x -> x < 150)) 151 | 152 | test "ra_forall b" <| not 153 | (ra [1..100] |> ResizeArray.forall (fun x -> x < 80)) 154 | 155 | test "ra_find" 156 | (ra [1..100] |> ResizeArray.find (fun x -> x > 50) = 51) 157 | 158 | test "ra_find b" 159 | (try ra [1..100] |> ResizeArray.find (fun x -> x > 180) |> ignore; false 160 | with _ -> true) 161 | 162 | test "ra_first" 163 | (ra [1..100] |> ResizeArray.tryPick (fun x -> if x > 50 then Some (x*x) else None) = Some (51*51)) 164 | 165 | test "ra_first b" 166 | (ra [1..100] |> ResizeArray.tryPick (fun x -> None) = None) 167 | 168 | test "ra_first c" 169 | (ra [] |> ResizeArray.tryPick (fun _ -> Some 42) = None) 170 | 171 | test "ra_tryfind" 172 | (ra [1..100] |> ResizeArray.tryFind (fun x -> x > 50) = Some 51) 173 | 174 | test "ra_tryfind b" 175 | (ra [1..100] |> ResizeArray.tryFind (fun x -> x > 180) = None) 176 | 177 | c := -1 178 | ResizeArray.iter2 (fun x y -> incr c; test "ra_iter2" (!c = x && !c = y)) (ra [0..100]) (ra [0..100]) 179 | test "ra_iter2" (!c = 100) 180 | 181 | test "ra_map2" 182 | (ResizeArray.map2 (+) (ra [0..100]) (ra [0..100]) =? [0..+2..200]) 183 | 184 | test "ra_choose" 185 | (ResizeArray.choose (fun x -> if x % 2 = 0 then Some (x/2) else None) (ra [0..100]) =? [0..50]) 186 | 187 | test "ra_filter" 188 | (ResizeArray.filter (fun x -> x % 2 = 0) (ra [0..100]) =? [0..+2..100]) 189 | 190 | test "ra_filter b" 191 | (ResizeArray.filter (fun x -> false) (ra [0..100]) =? []) 192 | 193 | test "ra_filter c" 194 | (ResizeArray.filter (fun x -> true) (ra [0..100]) =? [0..100]) 195 | 196 | let p1, p2 = ResizeArray.partition (fun x -> x % 2 = 0) (ra [0..100]) 197 | test "ra_partition" 198 | (p1 =? [0..+2..100] && p2 =? [1..+2..100]) 199 | 200 | test "ra_rev" 201 | (ResizeArray.rev (ra [0..100]) =? [100..-1 ..0]) 202 | 203 | test "ra_rev b" 204 | (ResizeArray.rev (ra [1]) =? [1]) 205 | 206 | test "ra_rev c" 207 | (ResizeArray.rev (ra []) =? []) 208 | 209 | test "ra_rev d" 210 | (ResizeArray.rev (ra [1; 2]) =? [2; 1]) 211 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.Set.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.Set module. 20 | module Tests.ExtCore.Collections.Set 21 | 22 | open System 23 | open NUnit.Framework 24 | //open FsCheck 25 | 26 | 27 | [] 28 | let foldi () : unit = 29 | let colors = 30 | Set.ofArray [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 31 | 32 | ([], colors) 33 | ||> Set.foldi (fun lst idx el -> 34 | (idx, el) :: lst) 35 | |> assertEqual [ 36 | 5, "Yellow"; 37 | 4, "Violet"; 38 | 3, "Red"; 39 | 2, "Orange"; 40 | 1, "Green"; 41 | 0, "Blue"; ] 42 | 43 | [] 44 | let mapToArray () : unit = 45 | let colors = 46 | Set.ofArray [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 47 | 48 | colors 49 | |> Set.mapToArray String.length 50 | |> assertEqual [| 51 | 4; 5; 6; 3; 6; 6 |] 52 | 53 | [] 54 | let init () : unit = 55 | let expected = 56 | Set.ofArray [| 'a' .. 'z' |] 57 | 58 | Set.init 26 <| fun i -> 59 | char (int 'a' + i) 60 | |> assertEqual expected 61 | 62 | [] 63 | let tryExtractMin () : unit = 64 | do 65 | let initialSet = Set.empty 66 | let minElement, remaining = 67 | Set.tryExtractMin initialSet 68 | 69 | minElement 70 | |> assertEqual None 71 | 72 | remaining 73 | |> assertEqual initialSet 74 | 75 | remaining 76 | |> assertSame initialSet 77 | 78 | do 79 | let initialSet = Set.ofArray [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 80 | let minElement, remaining = 81 | Set.tryExtractMin initialSet 82 | 83 | minElement 84 | |> assertEqual (Some "Blue") 85 | 86 | remaining 87 | |> assertEqual (Set.ofArray [| "Red"; "Orange"; "Yellow"; "Green"; "Violet" |]) 88 | 89 | [] 90 | let tryExtractMax () : unit = 91 | do 92 | let initialSet = Set.empty 93 | let maxElement, remaining = 94 | Set.tryExtractMax initialSet 95 | 96 | maxElement 97 | |> assertEqual None 98 | 99 | remaining 100 | |> assertEqual initialSet 101 | 102 | remaining 103 | |> assertSame initialSet 104 | 105 | do 106 | let maxElement, remaining = 107 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 108 | |> Set.ofArray 109 | |> Set.tryExtractMax 110 | 111 | maxElement 112 | |> assertEqual (Some "Yellow") 113 | 114 | remaining 115 | |> assertEqual (Set.ofArray [| "Red"; "Orange"; "Green"; "Blue"; "Violet" |]) 116 | 117 | [] 118 | let extractMin () : unit = 119 | let minElement, remaining = 120 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 121 | |> Set.ofArray 122 | |> Set.extractMin 123 | 124 | minElement 125 | |> assertEqual "Blue" 126 | 127 | remaining 128 | |> assertEqual (Set.ofArray [| "Red"; "Orange"; "Yellow"; "Green"; "Violet" |]) 129 | 130 | [] 131 | let extractMax () : unit = 132 | let maxElement, remaining = 133 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 134 | |> Set.ofArray 135 | |> Set.extractMax 136 | 137 | maxElement 138 | |> assertEqual "Yellow" 139 | 140 | remaining 141 | |> assertEqual (Set.ofArray [| "Red"; "Orange"; "Green"; "Blue"; "Violet" |]) 142 | 143 | [] 144 | let reduce () : unit = 145 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 146 | |> Set.ofArray 147 | |> Set.reduce (+) 148 | |> assertEqual "BlueGreenOrangeRedVioletYellow" 149 | 150 | [] 151 | let reduceBack () : unit = 152 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 153 | |> Set.ofArray 154 | |> Set.reduceBack (+) 155 | |> assertEqual "BlueGreenOrangeRedVioletYellow" 156 | 157 | [] 158 | let choose () : unit = 159 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 160 | |> Set.ofArray 161 | |> Set.choose (fun colorName -> 162 | let len = String.length colorName 163 | if len < 6 then Some len else None) 164 | |> assertEqual 165 | <| set [| 3; 4; 5 |] 166 | 167 | [] 168 | let tryPick () : unit = 169 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 170 | |> Set.ofArray 171 | |> Set.tryPick (fun colorName -> 172 | if colorName.StartsWith "T" then Some (String.length colorName) else None) 173 | |> assertEqual None 174 | 175 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 176 | |> Set.ofArray 177 | |> Set.tryPick (fun colorName -> 178 | if colorName.StartsWith "G" then Some (String.length colorName) else None) 179 | |> assertEqual (Some 5) 180 | 181 | [] 182 | let pick () : unit = 183 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 184 | |> Set.ofArray 185 | |> Set.pick (fun colorName -> 186 | if colorName.StartsWith "G" then Some (String.length colorName) else None) 187 | |> assertEqual 5 188 | 189 | [] 190 | let tryFind () : unit = 191 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 192 | |> Set.ofArray 193 | |> Set.tryFind (fun colorName -> 194 | colorName.StartsWith "T") 195 | |> assertEqual None 196 | 197 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 198 | |> Set.ofArray 199 | |> Set.tryFind (fun colorName -> 200 | colorName.StartsWith "G") 201 | |> assertEqual (Some "Green") 202 | 203 | [] 204 | let find () : unit = 205 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 206 | |> Set.ofArray 207 | |> Set.find (fun colorName -> 208 | colorName.StartsWith "G") 209 | |> assertEqual "Green" 210 | 211 | [] 212 | let mapPartition () : unit = 213 | let left, right = 214 | [| "Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Violet" |] 215 | |> Set.ofArray 216 | |> Set.mapPartition (fun colorName -> 217 | let len = String.length colorName 218 | if len % 2 = 0 then 219 | Choice1Of2 len 220 | else 221 | Choice2Of2 <| colorName.ToLower ()) 222 | 223 | left 224 | |> assertEqual (Set.ofArray [| 4; 6; 6; 6 |]) 225 | 226 | right 227 | |> assertEqual (Set.ofArray [| "red"; "green" |]) 228 | 229 | [] 230 | let symmetricDifference () : unit = 231 | Set.symmetricDifference Set.empty Set.empty 232 | |> assertEqual Set.empty 233 | 234 | Set.symmetricDifference (Set.ofArray [| 0..2..20 |]) (Set.ofArray [| 0..3..20 |]) 235 | |> assertEqual (Set.ofArray [| 2; 3; 4; 8; 9; 10; 14; 15; 16; 20 |]) 236 | 237 | [] 238 | let cartesian () : unit = 239 | Set.cartesian Set.empty Set.empty 240 | |> assertEqual Set.empty 241 | 242 | Set.cartesian 243 | (Set.ofArray [| "Red"; "Green"; "Blue" |]) 244 | (Set.ofArray [| 20; 30 |]) 245 | |> assertEqual (Set.ofArray 246 | [| 247 | "Blue", 20; 248 | "Blue", 30; 249 | "Green", 20; 250 | "Green", 30; 251 | "Red", 20; 252 | "Red", 30; |]) 253 | 254 | [] 255 | let collect () : unit = 256 | [| 0; 1; 1; 2; 3; 5; 8 |] 257 | |> Set.ofArray 258 | |> Set.collect (fun el -> 259 | Set.ofArray [| 260 | el; el + 1; el * 2 |]) 261 | |> assertEqual (Set.ofArray 262 | [| 0; 1; 2; 3; 4; 5; 6; 8; 9; 10; 16 |]) 263 | 264 | [] 265 | let condense () : unit = 266 | [| 7; 11; 13; 17; 19 |] 267 | |> Set.ofArray 268 | |> Set.condense (fun el -> 269 | Set.ofArray [| 0 .. el |]) 270 | |> assertEqual (Set.ofArray [| 0; 1; 2; 3; 4; 5; 6; 7 |]) 271 | 272 | [] 273 | let disjoint () : unit = 274 | Set.disjoint Set.empty Set.empty 275 | |> assertTrue 276 | 277 | Set.disjoint (Set.ofArray [| 3; 6; 9; 12; 15 |]) (Set.ofArray [| 7; 14; 21; 28; 35 |]) 278 | |> assertTrue 279 | 280 | Set.disjoint 281 | (Set.ofArray [| 0..20 |] |> Set.filter (fun el -> el % 2 = 0)) 282 | (Set.ofArray [| 0..20 |] |> Set.filter (fun el -> el % 3 = 0)) 283 | |> assertFalse 284 | 285 | [] 286 | let countWith () : unit = 287 | // Test case for an empty set. 288 | Set.empty 289 | |> Set.countWith (fun x -> 290 | x % 7 = 0) 291 | |> assertEqual 0 292 | 293 | // Sample usage test cases. 294 | [| 0; 1; 2; 3; 4; 5; 6; 8; 9; 10; 16 |] 295 | |> Set.ofArray 296 | |> Set.countWith (fun x -> 297 | x < 0) 298 | |> assertEqual 0 299 | 300 | [| 0; 1; 2; 3; 4; 5; 6; 8; 9; 10; 16 |] 301 | |> Set.ofArray 302 | |> Set.countWith (fun x -> 303 | x % 7 = 0) 304 | |> assertEqual 1 305 | 306 | [| 0; 1; 2; 3; 4; 5; 6; 8; 9; 10; 16 |] 307 | |> Set.ofArray 308 | |> Set.countWith (fun x -> 309 | x % 3 = 0) 310 | |> assertEqual 4 311 | 312 | 313 | module Cartesian = 314 | [] 315 | let fold () : unit = 316 | Assert.Ignore "Test not yet implemented." 317 | 318 | [] 319 | let foldBack () : unit = 320 | Assert.Ignore "Test not yet implemented." 321 | 322 | [] 323 | let iter () : unit = 324 | Assert.Ignore "Test not yet implemented." 325 | 326 | [] 327 | let map () : unit = 328 | Assert.Ignore "Test not yet implemented." 329 | 330 | [] 331 | let choose () : unit = 332 | Assert.Ignore "Test not yet implemented." 333 | 334 | -------------------------------------------------------------------------------- /ExtCore.Tests/Collections.VectorView.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Collections.VectorView module. 20 | module Tests.ExtCore.Collections.VectorView 21 | 22 | open System 23 | open NUnit.Framework 24 | //open FsCheck 25 | 26 | 27 | [] 28 | let dummy () : unit = 29 | Assert.Ignore "Test not yet implemented." 30 | 31 | -------------------------------------------------------------------------------- /ExtCore.Tests/Control.Agents.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the ExtCore.Control.Agents module. 20 | module Tests.ExtCore.Control.Agents 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/Control.Cps.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | // 20 | namespace Tests.ExtCore.Control.Cps 21 | 22 | open NUnit.Framework 23 | open FsCheck 24 | 25 | 26 | (* TODO : Implement tests for the workflows and modules in ExtCore.Control.Cps *) 27 | 28 | -------------------------------------------------------------------------------- /ExtCore.Tests/Control.Observable.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the ExtCore.Control.Observable module. 20 | module Tests.ExtCore.Control.Observable 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.AsyncChoice.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.AsyncChoice module. 20 | module Tests.ExtCore.Control.Collections.AsyncChoice 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | 26 | 27 | (* TODO : Implement tests for the AsyncChoice collections. *) 28 | 29 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.AsyncMaybe.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.AsyncMaybe module. 20 | module Tests.ExtCore.Control.Collections.AsyncMaybe 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | 26 | 27 | (* TODO : Implement tests for the AsyncMaybe collections. *) 28 | 29 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.AsyncProtectedState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.AsyncProtectedState module. 20 | module Tests.ExtCore.Control.Collections.AsyncProtectedState 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | 26 | 27 | 28 | (* TODO : Implement tests for the AsyncProtectedState collections. *) 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.AsyncState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.AsyncState module. 20 | module Tests.ExtCore.Control.Collections.AsyncState 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | 26 | 27 | (* TODO : Implement tests for the AsyncState collections. *) 28 | 29 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.Cont.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.Cps.Cont module. 20 | module Tests.ExtCore.Control.Collections.Cps.Cont 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.Cps.Cont.Array module. 29 | module Array = 30 | [] 31 | let map () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.ProtectedState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.ProtectedState module. 20 | module Tests.ExtCore.Control.Collections.ProtectedState 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.ProtectedState.Array module. 29 | module Array = 30 | [] 31 | let iter () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let iteri () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | [] 39 | let map () : unit = 40 | Assert.Ignore "Test not yet implemented." 41 | 42 | [] 43 | let mapi () : unit = 44 | Assert.Ignore "Test not yet implemented." 45 | 46 | 47 | /// Tests for the ExtCore.Control.Collections.ProtectedState.List module. 48 | module List = 49 | [] 50 | let map () : unit = 51 | Assert.Ignore "Test not yet implemented." 52 | 53 | 54 | /// Tests for the ExtCore.Control.Collections.ProtectedState.ArrayView module. 55 | module ArrayView = 56 | [] 57 | let iter () : unit = 58 | Assert.Ignore "Test not yet implemented." 59 | 60 | [] 61 | let iteri () : unit = 62 | Assert.Ignore "Test not yet implemented." 63 | 64 | [] 65 | let map () : unit = 66 | Assert.Ignore "Test not yet implemented." 67 | 68 | [] 69 | let mapi () : unit = 70 | Assert.Ignore "Test not yet implemented." 71 | 72 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.Reader.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.Reader module. 20 | module Tests.ExtCore.Control.Collections.Reader 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | 26 | 27 | /// Helper functions for implementing tests. 28 | [] 29 | module private ReaderTestHelpers = 30 | /// A subset of the F# language keywords. 31 | let keywords = Set.ofArray [| "if"; "then"; "elif"; "else"; "do"; "while"; "let"; "for"; |] 32 | 33 | 34 | /// Tests for the ExtCore.Control.Collections.Reader.Array module. 35 | module Array = 36 | [] 37 | let iter () : unit = 38 | // Test case for an empty array. 39 | do 40 | let keywordCount = ref 0 41 | 42 | let testFunc = 43 | Array.empty 44 | |> Reader.Array.iter (fun str -> 45 | reader { 46 | let! isKeyword = Set.contains str 47 | if isKeyword then 48 | incr keywordCount 49 | }) 50 | Reader.run testFunc keywords 51 | 52 | !keywordCount |> assertEqual 0 53 | 54 | // Sample usage test cases. 55 | do 56 | let keywordCount = ref 0 57 | 58 | let testFunc = 59 | [| "if"; "foo"; "<>"; "123"; "then"; |] 60 | |> Reader.Array.iter (fun str -> 61 | reader { 62 | let! isKeyword = Set.contains str 63 | if isKeyword then 64 | incr keywordCount 65 | }) 66 | Reader.run testFunc keywords 67 | 68 | !keywordCount |> assertEqual 2 69 | 70 | [] 71 | let iteri () : unit = 72 | // Test case for an empty array. 73 | do 74 | let keywordWeight = ref 0 75 | 76 | let testFunc = 77 | Array.empty 78 | |> Reader.Array.iteri (fun idx str -> 79 | reader { 80 | let! isKeyword = Set.contains str 81 | if isKeyword then 82 | keywordWeight := !keywordWeight + (idx + 1) 83 | }) 84 | Reader.run testFunc keywords 85 | 86 | !keywordWeight |> assertEqual 0 87 | 88 | // Sample usage test cases. 89 | do 90 | let keywordWeight = ref 0 91 | 92 | let testFunc = 93 | [| "if"; "foo"; "<>"; "123"; "then"; |] 94 | |> Reader.Array.iteri (fun idx str -> 95 | reader { 96 | let! isKeyword = Set.contains str 97 | if isKeyword then 98 | keywordWeight := !keywordWeight + (idx + 1) 99 | }) 100 | Reader.run testFunc keywords 101 | 102 | !keywordWeight |> assertEqual 6 103 | 104 | [] 105 | let map () : unit = 106 | // Test case for an empty array. 107 | do 108 | let testFunc = 109 | Array.empty 110 | |> Reader.Array.map (fun str -> 111 | reader { 112 | return! Set.contains str 113 | }) 114 | 115 | keywords 116 | |> Reader.run testFunc 117 | |> Array.isEmpty 118 | |> assertTrue 119 | 120 | // Sample usage test cases. 121 | do 122 | let testFunc = 123 | [| "if"; "foo"; "<>"; "123"; "then"; |] 124 | |> Reader.Array.map (fun str -> 125 | reader { 126 | return! Set.contains str 127 | }) 128 | keywords 129 | |> Reader.run testFunc 130 | |> assertEqual 131 | [| true; false; false; false; true; |] 132 | 133 | [] 134 | let mapi () : unit = 135 | // Test case for an empty array. 136 | do 137 | let testFunc = 138 | Array.empty 139 | |> Reader.Array.mapi (fun idx str -> 140 | reader { 141 | let! isKeyword = Set.contains str 142 | return 143 | if isKeyword then Some (sprintf "%i:%s" idx str) else None 144 | }) 145 | keywords 146 | |> Reader.run testFunc 147 | |> Array.isEmpty 148 | |> assertTrue 149 | 150 | // Sample usage test cases. 151 | do 152 | let testFunc = 153 | [| "if"; "foo"; "<>"; "123"; "then"; |] 154 | |> Reader.Array.mapi (fun idx str -> 155 | reader { 156 | let! isKeyword = Set.contains str 157 | return 158 | if isKeyword then Some (sprintf "%i:%s" idx str) else None 159 | }) 160 | keywords 161 | |> Reader.run testFunc 162 | |> assertEqual 163 | [| Some "0:if"; None; None; None; Some "4:then"; |] 164 | 165 | 166 | /// Tests for the ExtCore.Control.Collections.Reader.Set module. 167 | module Set = 168 | [] 169 | let iter () : unit = 170 | Assert.Ignore "Test not yet implemented." 171 | 172 | [] 173 | let iterBack () : unit = 174 | Assert.Ignore "Test not yet implemented." 175 | 176 | [] 177 | let map () : unit = 178 | Assert.Ignore "Test not yet implemented." 179 | 180 | [] 181 | let mapBack () : unit = 182 | Assert.Ignore "Test not yet implemented." 183 | 184 | [] 185 | let fold () : unit = 186 | Assert.Ignore "Test not yet implemented." 187 | 188 | [] 189 | let foldBack () : unit = 190 | Assert.Ignore "Test not yet implemented." 191 | 192 | 193 | /// Tests for the ExtCore.Control.Collections.Reader.IntSet module. 194 | module IntSet = 195 | [] 196 | let iter () : unit = 197 | Assert.Ignore "Test not yet implemented." 198 | 199 | [] 200 | let iterBack () : unit = 201 | Assert.Ignore "Test not yet implemented." 202 | 203 | [] 204 | let map () : unit = 205 | Assert.Ignore "Test not yet implemented." 206 | 207 | [] 208 | let mapBack () : unit = 209 | Assert.Ignore "Test not yet implemented." 210 | 211 | [] 212 | let fold () : unit = 213 | Assert.Ignore "Test not yet implemented." 214 | 215 | [] 216 | let foldBack () : unit = 217 | Assert.Ignore "Test not yet implemented." 218 | 219 | 220 | /// Tests for the ExtCore.Control.Collections.Reader.HashSet module. 221 | module HashSet = 222 | [] 223 | let iter () : unit = 224 | Assert.Ignore "Test not yet implemented." 225 | 226 | [] 227 | let iterBack () : unit = 228 | Assert.Ignore "Test not yet implemented." 229 | 230 | [] 231 | let map () : unit = 232 | Assert.Ignore "Test not yet implemented." 233 | 234 | [] 235 | let mapBack () : unit = 236 | Assert.Ignore "Test not yet implemented." 237 | 238 | [] 239 | let fold () : unit = 240 | Assert.Ignore "Test not yet implemented." 241 | 242 | [] 243 | let foldBack () : unit = 244 | Assert.Ignore "Test not yet implemented." 245 | 246 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.ReaderChoice.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.ReaderChoice module. 20 | module Tests.ExtCore.Control.Collections.ReaderChoice 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.ReaderChoice.Array module. 29 | module Array = 30 | [] 31 | let map () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let mapi () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | [] 39 | let map2 () : unit = 40 | Assert.Ignore "Test not yet implemented." 41 | 42 | [] 43 | let fold () : unit = 44 | Assert.Ignore "Test not yet implemented." 45 | 46 | [] 47 | let foldi () : unit = 48 | Assert.Ignore "Test not yet implemented." 49 | 50 | [] 51 | let init () : unit = 52 | Assert.Ignore "Test not yet implemented." 53 | 54 | [] 55 | let iter () : unit = 56 | Assert.Ignore "Test not yet implemented." 57 | 58 | [] 59 | let iteri () : unit = 60 | Assert.Ignore "Test not yet implemented." 61 | 62 | [] 63 | let reduce () : unit = 64 | Assert.Ignore "Test not yet implemented." 65 | 66 | 67 | /// Tests for the ExtCore.Control.Collections.ReaderChoice.List module. 68 | module List = 69 | [] 70 | let fold () : unit = 71 | Assert.Ignore "Test not yet implemented." 72 | 73 | [] 74 | let map2 () : unit = 75 | Assert.Ignore "Test not yet implemented." 76 | 77 | [] 78 | let mapi2 () : unit = 79 | Assert.Ignore "Test not yet implemented." 80 | 81 | [] 82 | let iter2 () : unit = 83 | Assert.Ignore "Test not yet implemented." 84 | 85 | 86 | /// Tests for the ExtCore.Control.Collections.ReaderChoice.Seq module. 87 | module Seq = 88 | [] 89 | let iter () : unit = 90 | Assert.Ignore "Test not yet implemented." 91 | 92 | 93 | /// Tests for the ExtCore.Control.Collections.ReaderChoice.Set module. 94 | module Set = 95 | [] 96 | let fold () : unit = 97 | Assert.Ignore "Test not yet implemented." 98 | 99 | [] 100 | let mapToArray () : unit = 101 | Assert.Ignore "Test not yet implemented." 102 | 103 | 104 | /// Tests for the ExtCore.Control.Collections.ReaderChoice.ArrayView module. 105 | module ArrayView = 106 | [] 107 | let fold () : unit = 108 | Assert.Ignore "Test not yet implemented." 109 | 110 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.ReaderMaybe.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.ReaderMaybe module. 20 | module Tests.ExtCore.Control.Collections.ReaderMaybe 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.ReaderMaybe.Array module. 29 | module Array = 30 | [] 31 | let map () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let mapi () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | [] 39 | let map2 () : unit = 40 | Assert.Ignore "Test not yet implemented." 41 | 42 | [] 43 | let fold () : unit = 44 | Assert.Ignore "Test not yet implemented." 45 | 46 | [] 47 | let foldi () : unit = 48 | Assert.Ignore "Test not yet implemented." 49 | 50 | [] 51 | let init () : unit = 52 | Assert.Ignore "Test not yet implemented." 53 | 54 | [] 55 | let iter () : unit = 56 | Assert.Ignore "Test not yet implemented." 57 | 58 | [] 59 | let iteri () : unit = 60 | Assert.Ignore "Test not yet implemented." 61 | 62 | [] 63 | let reduce () : unit = 64 | Assert.Ignore "Test not yet implemented." 65 | 66 | 67 | /// Tests for the ExtCore.Control.Collections.ReaderMaybe.List module. 68 | module List = 69 | [] 70 | let fold () : unit = 71 | Assert.Ignore "Test not yet implemented." 72 | 73 | [] 74 | let map2 () : unit = 75 | Assert.Ignore "Test not yet implemented." 76 | 77 | [] 78 | let mapi2 () : unit = 79 | Assert.Ignore "Test not yet implemented." 80 | 81 | [] 82 | let iter2 () : unit = 83 | Assert.Ignore "Test not yet implemented." 84 | 85 | 86 | /// Tests for the ExtCore.Control.Collections.ReaderMaybe.Seq module. 87 | module Seq = 88 | [] 89 | let iter () : unit = 90 | Assert.Ignore "Test not yet implemented." 91 | 92 | 93 | /// Tests for the ExtCore.Control.Collections.ReaderMaybe.Set module. 94 | module Set = 95 | [] 96 | let fold () : unit = 97 | Assert.Ignore "Test not yet implemented." 98 | 99 | [] 100 | let mapToArray () : unit = 101 | Assert.Ignore "Test not yet implemented." 102 | 103 | 104 | /// Tests for the ExtCore.Control.Collections.ReaderMaybe.ArrayView module. 105 | module ArrayView = 106 | [] 107 | let fold () : unit = 108 | Assert.Ignore "Test not yet implemented." 109 | 110 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.ReaderProtectedState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.ReaderProtectedState module. 20 | module Tests.ExtCore.Control.Collections.ReaderProtectedState 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.ReaderProtectedState.Array module. 29 | module Array = 30 | [] 31 | let iter () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let iteri () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | [] 39 | let map () : unit = 40 | Assert.Ignore "Test not yet implemented." 41 | 42 | [] 43 | let mapi () : unit = 44 | Assert.Ignore "Test not yet implemented." 45 | 46 | 47 | /// Tests for the ExtCore.Control.Collections.ReaderProtectedState.List module. 48 | module List = 49 | [] 50 | let map () : unit = 51 | Assert.Ignore "Test not yet implemented." 52 | 53 | 54 | /// Tests for the ExtCore.Control.Collections.ReaderProtectedState.ArrayView module. 55 | module ArrayView = 56 | [] 57 | let iter () : unit = 58 | Assert.Ignore "Test not yet implemented." 59 | 60 | [] 61 | let iteri () : unit = 62 | Assert.Ignore "Test not yet implemented." 63 | 64 | [] 65 | let map () : unit = 66 | Assert.Ignore "Test not yet implemented." 67 | 68 | [] 69 | let mapi () : unit = 70 | Assert.Ignore "Test not yet implemented." 71 | 72 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.ReaderState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.ReaderState module. 20 | module Tests.ExtCore.Control.Collections.ReaderState 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.ReaderState.Array module. 29 | module Array = 30 | [] 31 | let iter () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let iteri () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | [] 39 | let map () : unit = 40 | Assert.Ignore "Test not yet implemented." 41 | 42 | [] 43 | let mapi () : unit = 44 | Assert.Ignore "Test not yet implemented." 45 | 46 | [] 47 | let mapBack () : unit = 48 | Assert.Ignore "Test not yet implemented." 49 | 50 | [] 51 | let mapiBack () : unit = 52 | Assert.Ignore "Test not yet implemented." 53 | 54 | [] 55 | let map2 () : unit = 56 | Assert.Ignore "Test not yet implemented." 57 | 58 | [] 59 | let mapi2 () : unit = 60 | Assert.Ignore "Test not yet implemented." 61 | 62 | [] 63 | let fold () : unit = 64 | Assert.Ignore "Test not yet implemented." 65 | 66 | [] 67 | let foldi () : unit = 68 | Assert.Ignore "Test not yet implemented." 69 | 70 | 71 | /// Tests for the ExtCore.Control.Collections.ReaderState.TaggedArray module. 72 | module TaggedArray = 73 | [] 74 | let mapi () : unit = 75 | Assert.Ignore "Test not yet implemented." 76 | 77 | [] 78 | let mapiBack () : unit = 79 | Assert.Ignore "Test not yet implemented." 80 | 81 | [] 82 | let foldi () : unit = 83 | Assert.Ignore "Test not yet implemented." 84 | 85 | 86 | /// Tests for the ExtCore.Control.Collections.ReaderState.ArrayView module. 87 | module ArrayView = 88 | [] 89 | let iter () : unit = 90 | Assert.Ignore "Test not yet implemented." 91 | 92 | [] 93 | let iteri () : unit = 94 | Assert.Ignore "Test not yet implemented." 95 | 96 | [] 97 | let map () : unit = 98 | Assert.Ignore "Test not yet implemented." 99 | 100 | [] 101 | let mapi () : unit = 102 | Assert.Ignore "Test not yet implemented." 103 | 104 | 105 | /// Tests for the ExtCore.Control.Collections.ReaderState.Set module. 106 | module Set = 107 | [] 108 | let iter () : unit = 109 | Assert.Ignore "Test not yet implemented." 110 | 111 | [] 112 | let iterBack () : unit = 113 | Assert.Ignore "Test not yet implemented." 114 | 115 | [] 116 | let map () : unit = 117 | Assert.Ignore "Test not yet implemented." 118 | 119 | [] 120 | let mapBack () : unit = 121 | Assert.Ignore "Test not yet implemented." 122 | 123 | [] 124 | let fold () : unit = 125 | Assert.Ignore "Test not yet implemented." 126 | 127 | [] 128 | let foldBack () : unit = 129 | Assert.Ignore "Test not yet implemented." 130 | 131 | 132 | /// Tests for the ExtCore.Control.Collections.ReaderState.IntSet module. 133 | module IntSet = 134 | [] 135 | let iter () : unit = 136 | Assert.Ignore "Test not yet implemented." 137 | 138 | [] 139 | let iterBack () : unit = 140 | Assert.Ignore "Test not yet implemented." 141 | 142 | [] 143 | let map () : unit = 144 | Assert.Ignore "Test not yet implemented." 145 | 146 | [] 147 | let mapBack () : unit = 148 | Assert.Ignore "Test not yet implemented." 149 | 150 | [] 151 | let fold () : unit = 152 | Assert.Ignore "Test not yet implemented." 153 | 154 | [] 155 | let foldBack () : unit = 156 | Assert.Ignore "Test not yet implemented." 157 | 158 | 159 | /// Tests for the ExtCore.Control.Collections.ReaderState.HashSet module. 160 | module HashSet = 161 | [] 162 | let iter () : unit = 163 | Assert.Ignore "Test not yet implemented." 164 | 165 | [] 166 | let iterBack () : unit = 167 | Assert.Ignore "Test not yet implemented." 168 | 169 | [] 170 | let map () : unit = 171 | Assert.Ignore "Test not yet implemented." 172 | 173 | [] 174 | let mapBack () : unit = 175 | Assert.Ignore "Test not yet implemented." 176 | 177 | [] 178 | let fold () : unit = 179 | Assert.Ignore "Test not yet implemented." 180 | 181 | [] 182 | let foldBack () : unit = 183 | Assert.Ignore "Test not yet implemented." 184 | 185 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.StateCont.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.Cps.StateCont module. 20 | module Tests.ExtCore.Control.Collections.Cps.StateCont 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.Cps.StateCont.Array module. 29 | module Array = 30 | [] 31 | let map () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | [] 35 | let mapi () : unit = 36 | Assert.Ignore "Test not yet implemented." 37 | 38 | -------------------------------------------------------------------------------- /ExtCore.Tests/ControlCollections.StatefulChoice.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Unit tests for the ExtCore.Control.Collections.StatefulChoice module. 20 | module Tests.ExtCore.Control.Collections.StatefulChoice 21 | 22 | open ExtCore.Control 23 | open ExtCore.Control.Collections 24 | open NUnit.Framework 25 | //open FsCheck 26 | 27 | 28 | /// Tests for the ExtCore.Control.Collections.StatefulChoice.Array module. 29 | module Array = 30 | [] 31 | let map () : unit = 32 | Assert.Ignore "Test not yet implemented." 33 | 34 | -------------------------------------------------------------------------------- /ExtCore.Tests/ExtCore.Tests.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp1.1;netcoreapp2.0;net45 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 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /ExtCore.Tests/IO.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the modules in the ExtCore.IO namespace. 20 | module Tests.ExtCore.IO 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/NativeInterop.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the modules in the ExtCore.NativeInterop namespace. 20 | module Tests.ExtCore.NativeInterop 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/Net.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | /// Tests for the modules in the ExtCore.Net namespace. 20 | module Tests.ExtCore.Net 21 | 22 | open NUnit.Framework 23 | 24 | 25 | (* TODO *) 26 | [] 27 | let dummy () = 28 | Assert.Ignore "Test not yet implemented." 29 | 30 | -------------------------------------------------------------------------------- /ExtCore.Tests/RefCountEnumerable.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2015 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace Tests.ExtCore 20 | 21 | open System.Collections.Generic 22 | open System.Runtime.CompilerServices 23 | open System.Threading 24 | 25 | 26 | /// 27 | /// An instance which wraps another enumerator 28 | /// and decrements a reference counter when disposed. 29 | /// This class is used primarily in unit tests to track whether enumerators are disposed properly after use. 30 | /// 31 | [] 32 | type RefCountEnumerator<'T> (enumeratorRefCount : StrongBox, enumerator : IEnumerator<'T>) = 33 | /// If zero, indicates this instance has not been disposed; 34 | /// otherwise, this instance has been disposed. 35 | let mutable isDisposed = 0 36 | 37 | do 38 | // Increment the enumerator reference count upon creation. 39 | Interlocked.Increment &enumeratorRefCount.Value |> ignore 40 | 41 | interface System.IDisposable with 42 | member __.Dispose () = 43 | // Only perform disposal operations once, even if Dispose() is called multiple times. 44 | if Interlocked.CompareExchange (&isDisposed, 1, 0) = 0 then 45 | // Decrement the enumerator reference count. 46 | Interlocked.Decrement &enumeratorRefCount.Value |> ignore 47 | 48 | // Dispose the wrapped enumerator. 49 | enumerator.Dispose () 50 | 51 | interface IEnumerator<'T> with 52 | member __.Current = 53 | enumerator.Current 54 | 55 | interface System.Collections.IEnumerator with 56 | member __.Current = 57 | upcast enumerator.Current 58 | 59 | member __.MoveNext () = 60 | enumerator.MoveNext () 61 | 62 | member __.Reset () = 63 | enumerator.Reset () 64 | 65 | /// 66 | /// Wraps another to track when enumerators 67 | /// created for the enumerable are disposed. 68 | /// 69 | [] 70 | type RefCountEnumerable<'T> (enumerable : seq<'T>) = 71 | /// The number of enumerators which have been created for the enumerable 72 | /// but not yet disposed. 73 | let enumeratorRefCount = StrongBox 0 74 | 75 | /// Returns the number of enumerator instances created for the underlying 76 | /// enumeration which have not yet been disposed. 77 | member __.EnumeratorReferenceCount = 78 | Volatile.Read &enumeratorRefCount.Value 79 | 80 | member private __.GetRefCountEnumerator () = 81 | /// An enumerator from the underlying enumerable. 82 | let underlyingEnumerator = enumerable.GetEnumerator () 83 | 84 | // Wrap the enumerator in a reference-counting wrapper and return it. 85 | new RefCountEnumerator<'T> (enumeratorRefCount, underlyingEnumerator) 86 | 87 | interface IEnumerable<'T> with 88 | member this.GetEnumerator () = 89 | this.GetRefCountEnumerator () :> IEnumerator<'T> 90 | 91 | interface System.Collections.IEnumerable with 92 | member this.GetEnumerator () = 93 | this.GetRefCountEnumerator () :> System.Collections.IEnumerator 94 | 95 | -------------------------------------------------------------------------------- /ExtCore.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ExtCore.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ExtCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2000 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ExtCore", "ExtCore\ExtCore.fsproj", "{AE097A63-ECC1-43FC-98CD-EF943B690012}" 7 | EndProject 8 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ExtCore.Tests", "ExtCore.Tests\ExtCore.Tests.fsproj", "{85B78E3D-ABFD-4A79-A9F7-26B586C56A94}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{308ECB02-6B2C-4D9F-94AF-32D98BAD9A5C}" 11 | ProjectSection(SolutionItems) = preProject 12 | appveyor.yml = appveyor.yml 13 | install_dotnet.ps1 = install_dotnet.ps1 14 | EndProjectSection 15 | EndProject 16 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ExtCore.Benchmarks", "ExtCore.Benchmarks\ExtCore.Benchmarks.fsproj", "{574DB1BE-8CF2-4B57-9B38-A991E326ABDF}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug (net40)|Any CPU = Debug (net40)|Any CPU 21 | Debug (net45)|Any CPU = Debug (net45)|Any CPU 22 | Debug (profile259)|Any CPU = Debug (profile259)|Any CPU 23 | Debug (profile47)|Any CPU = Debug (profile47)|Any CPU 24 | Debug (profile7)|Any CPU = Debug (profile7)|Any CPU 25 | Debug (profile78)|Any CPU = Debug (profile78)|Any CPU 26 | Debug|Any CPU = Debug|Any CPU 27 | Release (net40)|Any CPU = Release (net40)|Any CPU 28 | Release (net45)|Any CPU = Release (net45)|Any CPU 29 | Release (profile259)|Any CPU = Release (profile259)|Any CPU 30 | Release (profile47)|Any CPU = Release (profile47)|Any CPU 31 | Release (profile7)|Any CPU = Release (profile7)|Any CPU 32 | Release (profile78)|Any CPU = Release (profile78)|Any CPU 33 | Release|Any CPU = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 36 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (net40)|Any CPU.ActiveCfg = Debug|Any CPU 37 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (net40)|Any CPU.Build.0 = Debug|Any CPU 38 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (net45)|Any CPU.ActiveCfg = Debug|Any CPU 39 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (net45)|Any CPU.Build.0 = Debug|Any CPU 40 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile259)|Any CPU.ActiveCfg = Debug|Any CPU 41 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile259)|Any CPU.Build.0 = Debug|Any CPU 42 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile47)|Any CPU.ActiveCfg = Debug|Any CPU 43 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile47)|Any CPU.Build.0 = Debug|Any CPU 44 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile7)|Any CPU.ActiveCfg = Debug|Any CPU 45 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile7)|Any CPU.Build.0 = Debug|Any CPU 46 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile78)|Any CPU.ActiveCfg = Debug|Any CPU 47 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug (profile78)|Any CPU.Build.0 = Debug|Any CPU 48 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (net40)|Any CPU.ActiveCfg = Release|Any CPU 51 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (net40)|Any CPU.Build.0 = Release|Any CPU 52 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (net45)|Any CPU.ActiveCfg = Release|Any CPU 53 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (net45)|Any CPU.Build.0 = Release|Any CPU 54 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile259)|Any CPU.ActiveCfg = Release|Any CPU 55 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile259)|Any CPU.Build.0 = Release|Any CPU 56 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile47)|Any CPU.ActiveCfg = Release|Any CPU 57 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile47)|Any CPU.Build.0 = Release|Any CPU 58 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile7)|Any CPU.ActiveCfg = Release|Any CPU 59 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile7)|Any CPU.Build.0 = Release|Any CPU 60 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile78)|Any CPU.ActiveCfg = Release|Any CPU 61 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release (profile78)|Any CPU.Build.0 = Release|Any CPU 62 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release|Any CPU.ActiveCfg = Release|Any CPU 63 | {AE097A63-ECC1-43FC-98CD-EF943B690012}.Release|Any CPU.Build.0 = Release|Any CPU 64 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (net40)|Any CPU.ActiveCfg = Debug|Any CPU 65 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (net40)|Any CPU.Build.0 = Debug|Any CPU 66 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (net45)|Any CPU.ActiveCfg = Debug|Any CPU 67 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (net45)|Any CPU.Build.0 = Debug|Any CPU 68 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile259)|Any CPU.ActiveCfg = Debug|Any CPU 69 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile259)|Any CPU.Build.0 = Debug|Any CPU 70 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile47)|Any CPU.ActiveCfg = Debug|Any CPU 71 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile47)|Any CPU.Build.0 = Debug|Any CPU 72 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile7)|Any CPU.ActiveCfg = Debug|Any CPU 73 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile7)|Any CPU.Build.0 = Debug|Any CPU 74 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile78)|Any CPU.ActiveCfg = Debug|Any CPU 75 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug (profile78)|Any CPU.Build.0 = Debug|Any CPU 76 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 77 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Debug|Any CPU.Build.0 = Debug|Any CPU 78 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (net40)|Any CPU.ActiveCfg = Release|Any CPU 79 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (net40)|Any CPU.Build.0 = Release|Any CPU 80 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (net45)|Any CPU.ActiveCfg = Release|Any CPU 81 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (net45)|Any CPU.Build.0 = Release|Any CPU 82 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile259)|Any CPU.ActiveCfg = Release|Any CPU 83 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile259)|Any CPU.Build.0 = Release|Any CPU 84 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile47)|Any CPU.ActiveCfg = Release|Any CPU 85 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile47)|Any CPU.Build.0 = Release|Any CPU 86 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile7)|Any CPU.ActiveCfg = Release|Any CPU 87 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile7)|Any CPU.Build.0 = Release|Any CPU 88 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile78)|Any CPU.ActiveCfg = Release|Any CPU 89 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release (profile78)|Any CPU.Build.0 = Release|Any CPU 90 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release|Any CPU.ActiveCfg = Release|Any CPU 91 | {85B78E3D-ABFD-4A79-A9F7-26B586C56A94}.Release|Any CPU.Build.0 = Release|Any CPU 92 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (net40)|Any CPU.ActiveCfg = Debug|Any CPU 93 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (net40)|Any CPU.Build.0 = Debug|Any CPU 94 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (net45)|Any CPU.ActiveCfg = Debug|Any CPU 95 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (net45)|Any CPU.Build.0 = Debug|Any CPU 96 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile259)|Any CPU.ActiveCfg = Debug|Any CPU 97 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile259)|Any CPU.Build.0 = Debug|Any CPU 98 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile47)|Any CPU.ActiveCfg = Debug|Any CPU 99 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile47)|Any CPU.Build.0 = Debug|Any CPU 100 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile7)|Any CPU.ActiveCfg = Debug|Any CPU 101 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile7)|Any CPU.Build.0 = Debug|Any CPU 102 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile78)|Any CPU.ActiveCfg = Debug|Any CPU 103 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug (profile78)|Any CPU.Build.0 = Debug|Any CPU 104 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 105 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Debug|Any CPU.Build.0 = Debug|Any CPU 106 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (net40)|Any CPU.ActiveCfg = Release|Any CPU 107 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (net40)|Any CPU.Build.0 = Release|Any CPU 108 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (net45)|Any CPU.ActiveCfg = Release|Any CPU 109 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (net45)|Any CPU.Build.0 = Release|Any CPU 110 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile259)|Any CPU.ActiveCfg = Release|Any CPU 111 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile259)|Any CPU.Build.0 = Release|Any CPU 112 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile47)|Any CPU.ActiveCfg = Release|Any CPU 113 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile47)|Any CPU.Build.0 = Release|Any CPU 114 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile7)|Any CPU.ActiveCfg = Release|Any CPU 115 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile7)|Any CPU.Build.0 = Release|Any CPU 116 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile78)|Any CPU.ActiveCfg = Release|Any CPU 117 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release (profile78)|Any CPU.Build.0 = Release|Any CPU 118 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release|Any CPU.ActiveCfg = Release|Any CPU 119 | {574DB1BE-8CF2-4B57-9B38-A991E326ABDF}.Release|Any CPU.Build.0 = Release|Any CPU 120 | EndGlobalSection 121 | GlobalSection(SolutionProperties) = preSolution 122 | HideSolutionNode = FALSE 123 | EndGlobalSection 124 | GlobalSection(ExtensibilityGlobals) = postSolution 125 | SolutionGuid = {5965511C-D154-4A79-BBB0-5961938C4A89} 126 | EndGlobalSection 127 | EndGlobal 128 | -------------------------------------------------------------------------------- /ExtCore/Args.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2005-2009 Microsoft Corporation 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore.Args 21 | 22 | open ExtCore 23 | 24 | (* TODO : Replace the code from the F# PowerPack with a new implementation 25 | which doesn't require the use of mutable state (e.g., ref cells) 26 | and which does allow the use of arbitrary parser functions for 27 | parsing flag values in a type-safe way. For example, this would 28 | allow DateTime values to be parsed directly from the string then 29 | returned to the user, instead of parsing the value as a string then 30 | needing to convert/validate it manually. *) 31 | 32 | //// 33 | //type TypedArgInfo<'T> = { 34 | // // 35 | // ShortName : char option; 36 | // // 37 | // ShortAliases : Set; 38 | // // 39 | // Name : string; 40 | // // 41 | // Aliases : Set; 42 | // // 43 | // Description : string option; 44 | // // 45 | // DefaultValue : 'T option; 46 | //} 47 | // 48 | //module Example = 49 | // /// Help options. 50 | // let helpArgInfo : TypedArgInfo = { 51 | // ShortName = Some 'h'; 52 | // ShortAliases = Set.singleton '?'; 53 | // Name = "help"; 54 | // Aliases = Set.empty; 55 | // Description = Some "Display this list of options."; 56 | // DefaultValue = None; 57 | // } 58 | 59 | 60 | (* The code below is from the F# PowerPack and is only temporary -- 61 | eventually it will be replaced with a new, functional-style API. *) 62 | 63 | #nowarn "44" // Disable warnings from [] 64 | 65 | /// The spec value describes the action of the argument, 66 | /// and whether it expects a following parameter. 67 | [] 68 | type ArgType = 69 | // 70 | | Clear of bool ref 71 | // 72 | | Float of (float -> unit) 73 | // 74 | | Int of (int -> unit) 75 | // 76 | | Rest of (string -> unit) 77 | // 78 | | Set of bool ref 79 | // 80 | | String of (string -> unit) 81 | // 82 | | Unit of (unit -> unit) 83 | 84 | // 85 | type ArgInfo = { 86 | /// The name of the argument. 87 | Name : string; 88 | /// The argument type and action of the argument. 89 | Type : ArgType; 90 | /// The usage help associated with the argument. 91 | HelpText : string; 92 | } with 93 | /// Create an ArgInfo instance. 94 | static member Create (name, argType, helpText) = 95 | { Name = name; 96 | Type = argType; 97 | HelpText = helpText; } 98 | 99 | /// When thrown, the string will be displayed to the user (usually printed to the console). 100 | exception private ShowText of string 101 | 102 | // 103 | [] 104 | type ArgParser () = 105 | static let getUsage specs (usageText : string) = 106 | let sb = System.Text.StringBuilder 100 107 | 108 | sb.AppendLine usageText |> ignore 109 | 110 | specs 111 | |> List.iter (fun (arg : ArgInfo) -> 112 | let argDisplayType = 113 | match arg.Type with 114 | | Unit _ 115 | | Set _ 116 | | Clear _ -> 117 | None 118 | | String _ -> 119 | Some "" 120 | | Int _ -> 121 | Some "" 122 | | Float _ -> 123 | Some "" 124 | | Rest _ -> 125 | Some "..." 126 | 127 | match argDisplayType with 128 | | None -> 129 | Printf.bprintfn sb "\t%s: %s" arg.Name arg.HelpText 130 | | Some displayType -> 131 | Printf.bprintfn sb "\t%s %s: %s" arg.Name displayType arg.HelpText) 132 | 133 | // Append the help options. 134 | sb.AppendLine "\t--help: display this list of options" |> ignore 135 | sb.AppendLine "\t-help: display this list of options" |> ignore 136 | 137 | // Return the usage text. 138 | sb.ToString () 139 | 140 | /// Parse some of the arguments given by 'argv', starting at the given position. 141 | static member ParsePartial (cursor, argv, argSpecs : ArgInfo list, ?other, ?usageText) = 142 | let other = defaultArg other ignore 143 | let usageText = defaultArg usageText "" 144 | let nargs = Array.length argv 145 | incr cursor 146 | let specs = 147 | argSpecs 148 | |> List.map (fun (arg : ArgInfo) -> 149 | arg.Name, arg.Type) 150 | 151 | while !cursor < nargs do 152 | let arg = argv.[!cursor] 153 | let rec findMatchingArg args = 154 | match args with 155 | | [] -> 156 | // If any of the supplied arguments is a help switch, immediately print the help text and exit. 157 | if arg = "-help" || arg = "--help" || arg = "/help" || arg = "/help" || arg = "/?" then 158 | raise <| ShowText (getUsage argSpecs usageText) 159 | 160 | // Note: for '/abc/def' does not count as an argument 161 | // Note: '/abc' does 162 | elif arg.Length > 0 && (arg.[0] = '-' || (arg.[0] = '/' && not (arg.Length > 1 && arg.[1..].Contains "/"))) then 163 | let msg = 164 | sprintf "Unrecognized argument: %s" arg 165 | + System.Environment.NewLine 166 | + getUsage argSpecs usageText 167 | raise <| ShowText msg 168 | 169 | else 170 | other arg 171 | incr cursor 172 | 173 | | ((s, action) :: _) when s = arg -> 174 | let getSecondArg () = 175 | if !cursor + 1 >= nargs then 176 | let msg = 177 | sprintf "option %s needs an argument." s 178 | + System.Environment.NewLine 179 | + getUsage argSpecs usageText 180 | raise <| ShowText msg 181 | argv.[!cursor + 1] 182 | 183 | match action with 184 | | Unit f -> 185 | f () 186 | incr cursor 187 | | Set f -> 188 | f := true 189 | incr cursor 190 | | Clear f -> 191 | f := false 192 | incr cursor 193 | | String f -> 194 | let arg2 = getSecondArg () 195 | f arg2 196 | cursor := !cursor + 2 197 | | Int f -> 198 | let arg2 = 199 | let arg2 = getSecondArg () 200 | try int32 arg2 201 | with _ -> 202 | raise <| ShowText (getUsage argSpecs usageText) 203 | f arg2 204 | cursor := !cursor + 2 205 | | Float f -> 206 | let arg2 = 207 | let arg2 = getSecondArg () 208 | try float arg2 209 | with _ -> 210 | raise <| ShowText (getUsage argSpecs usageText) 211 | f arg2 212 | cursor := !cursor + 2 213 | | Rest f -> 214 | incr cursor 215 | while !cursor < nargs do 216 | f argv.[!cursor] 217 | incr cursor 218 | 219 | | (_ :: more) -> 220 | findMatchingArg more 221 | 222 | findMatchingArg specs 223 | 224 | #if FX_NO_SYSTEM_CONSOLE 225 | #else 226 | 227 | /// Prints the help for each argument. 228 | static member Usage (specs, ?usage) = 229 | defaultArg usage "" 230 | |> getUsage (Array.toList specs) 231 | |> System.Console.Error.WriteLine 232 | 233 | #if FX_NO_COMMAND_LINE_ARGS 234 | #else 235 | 236 | /// Parse the arguments given by System.Environment.GetEnvironmentVariables() 237 | /// according to the argument processing specifications "specs". 238 | /// Args begin with "-". Non-arguments are passed to "f" in 239 | /// order. "use" is printed as part of the usage line if an error occurs. 240 | static member Parse (specs, ?other, ?usageText) = 241 | let current = ref 0 242 | let argv = System.Environment.GetCommandLineArgs () 243 | try 244 | ArgParser.ParsePartial ( 245 | current, argv, Array.toList specs, ?other = other, ?usageText = usageText) 246 | with 247 | | ShowText text -> 248 | System.Console.Error.WriteLine text 249 | System.Console.Error.Flush () 250 | exit 1 251 | | _ -> 252 | reraise () 253 | #endif 254 | #endif 255 | -------------------------------------------------------------------------------- /ExtCore/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | module internal AssemblyInfo 21 | 22 | open System 23 | open System.Reflection 24 | open System.Resources 25 | open System.Runtime.CompilerServices 26 | open System.Runtime.InteropServices 27 | open System.Security 28 | 29 | #if FX_ATLEAST_PORTABLE || NETSTANDARD1_6 30 | #else 31 | open System.Security.Permissions 32 | #endif 33 | 34 | [] 35 | #if FX_ATLEAST_PORTABLE 36 | #else 37 | [] 38 | [] 39 | #endif 40 | 41 | // This assembly is CLS-compliant. 42 | // TODO : Enable this once we can verify that the assembly is actually CLS-compliant. 43 | //[] 44 | 45 | // Only allow types derived from System.Exception to be thrown -- 46 | // any other types should be automatically wrapped. 47 | [] 48 | 49 | // Security-related stuff. 50 | //[] 51 | //[] 52 | 53 | (* Makes internal modules, types, and functions visible 54 | to the test project so they can be unit-tested. *) 55 | [] 56 | 57 | #if FX_ATLEAST_PORTABLE || NETSTANDARD1_6 58 | #else 59 | (* Dependency hints for Ngen *) 60 | [] 61 | [] 62 | [] 63 | [] 64 | #endif 65 | 66 | (* Automatically open the basic namespaces, as in FSharp.Core. *) 67 | [] 68 | [] 69 | // These are disabled, for now, to avoid cluttering up everyone's default contexts. 70 | // If it seems reasonable to do so, enable these prior to releasing ExtCore 1.0. 71 | //[] 72 | //[] 73 | 74 | (* Create an AssemblyConfiguration attribute with relevant conditional compilation symbols 75 | defined when this assembly was compiled. This can be useful for diagnostic purposes. *) 76 | #if PROTO_COMPILER 77 | #if DEBUG 78 | #if TRACE 79 | [] 80 | #else 81 | [] 82 | #endif 83 | #else 84 | #if TRACE 85 | [] 86 | #else 87 | [] 88 | #endif 89 | #endif 90 | 91 | #else 92 | 93 | #if DEBUG 94 | #if TRACE 95 | [] 96 | #else 97 | [] 98 | #endif 99 | #else 100 | #if TRACE 101 | [] 102 | #else 103 | [] 104 | #endif 105 | #endif 106 | 107 | #endif 108 | 109 | (* F# considers modules which only contain attributes to be empty; 110 | so, we appease the compiler by adding an empty function. *) 111 | do () 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /ExtCore/Collections.Multimap.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2014 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace ExtCore.Collections 20 | 21 | open ExtCore 22 | 23 | 24 | /// Immutable multimaps. Elements are ordered by F# generic comparison. 25 | type Multimap<'T, 'Key 26 | when 'T : comparison 27 | and 'Key : comparison> = 28 | Map<'T, Set<'Key>> 29 | 30 | /// Functional programming operators related to the Multimap<_,_> type. 31 | [] 32 | module Multimap = 33 | /// The empty multimap. 34 | [] 35 | let empty : Multimap<'T, 'Key> = 36 | Map.empty 37 | 38 | /// Is the multimap empty? 39 | [] 40 | let isEmpty (set : Multimap<'T, 'Key>) = 41 | // Preconditions 42 | checkNonNull "set" set 43 | 44 | Map.isEmpty set 45 | 46 | // 47 | [] 48 | let singleton key value : Multimap<'T, 'Key> = 49 | Map.singleton key (Set.singleton value) 50 | 51 | // 52 | [] 53 | let add key value (map : Multimap<'T, 'Key>) : Multimap<'T, 'Key> = 54 | // Preconditions 55 | checkNonNull "map" map 56 | 57 | // If the key already has a value set associated with it, update the set with the value; 58 | // otherwise, add a new value set to the map for this key. 59 | match Map.tryFind key map with 60 | | None -> 61 | Map.add key (Set.singleton value) map 62 | | Some valueSet -> 63 | Map.add key (Set.add value valueSet) map 64 | 65 | // 66 | [] 67 | let remove key value (map : Multimap<'T, 'Key>) : Multimap<'T, 'Key> = 68 | // Preconditions 69 | checkNonNull "map" map 70 | 71 | match Map.tryFind key map with 72 | | None -> 73 | map 74 | | Some valueSet -> 75 | // Remove the value from the value set. 76 | let valueSet = Set.remove value valueSet 77 | 78 | // If the value set is now empty, remove this key's entry from the map. 79 | // Otherwise, update the entry with the updated value set. 80 | if Set.isEmpty valueSet then 81 | Map.remove key map 82 | else 83 | Map.add key valueSet map 84 | -------------------------------------------------------------------------------- /ExtCore/Collections.Multiset.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2014 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace ExtCore.Collections 20 | 21 | open ExtCore 22 | 23 | 24 | /// Immutable multisets. Elements are ordered by F# generic comparison. 25 | type Multiset<'T when 'T : comparison> = Map<'T, uint32> 26 | 27 | /// Functional programming operators related to the Multiset<_> type. 28 | [] 29 | module Multiset = 30 | /// The empty multiset. 31 | [] 32 | let empty : Multiset<'T> = 33 | Map.empty 34 | 35 | /// Is the multiset empty? 36 | [] 37 | let isEmpty (set : Multiset<'T>) = 38 | // Preconditions 39 | checkNonNull "set" set 40 | 41 | Map.isEmpty set 42 | 43 | /// The total number of elements in the multiset. 44 | [] 45 | let count (set : Multiset<'T>) : int64 = 46 | // Preconditions 47 | checkNonNull "set" set 48 | 49 | (0L, set) 50 | ||> Map.fold (fun count _ cardinality -> 51 | Checked.(+) (int64 cardinality) count) 52 | 53 | /// The number of distinct elements in the multiset. 54 | [] 55 | let countDistinct (set : Multiset<'T>) = 56 | // Preconditions 57 | checkNonNull "set" set 58 | 59 | Map.count set 60 | 61 | // 62 | [] 63 | let contains value (set : Multiset<'T>) = 64 | // Preconditions 65 | checkNonNull "set" set 66 | 67 | Map.containsKey value set 68 | 69 | // 70 | [] 71 | let card value (set : Multiset<'T>) = 72 | // Preconditions 73 | checkNonNull "set" set 74 | 75 | set 76 | |> Map.tryFind value 77 | |> Option.fill 0u 78 | 79 | // 80 | [] 81 | let singleton value : Multiset<'T> = 82 | Map.singleton value 1u 83 | 84 | // 85 | [] 86 | let add value (set : Multiset<'T>) : Multiset<'T> = 87 | // Preconditions 88 | checkNonNull "set" set 89 | 90 | // If the underlying map already contains the value as a key, increment the value's cardinality 91 | // and return; otherwise, add a new entry to the map for this value. 92 | match Map.tryFind value set with 93 | | None -> 94 | Map.add value 1u set 95 | | Some card -> 96 | Map.add value (Checked.(+) card 1u) set 97 | 98 | // 99 | [] 100 | let addMany value count (set : Multiset<'T>) : Multiset<'T> = 101 | // Preconditions 102 | checkNonNull "set" set 103 | if count < 0 then 104 | argOutOfRange "count" "Cannot add a negative number of elements to the set." 105 | 106 | // If no elements are being added, just return the input set. 107 | if count = 0 then set 108 | else 109 | // If the underlying map already contains the value as a key, increment the value's cardinality by the specified count 110 | // and return; otherwise, add a new entry to the map for this value. 111 | match Map.tryFind value set with 112 | | None -> 113 | Map.add value (uint32 count) set 114 | | Some card -> 115 | Map.add value (Checked.(+) card (uint32 count)) set 116 | 117 | // 118 | [] 119 | let remove value (set : Multiset<'T>) : Multiset<'T> = 120 | // Preconditions 121 | checkNonNull "set" set 122 | 123 | match Map.tryFind value set with 124 | | None -> 125 | set 126 | | Some card -> 127 | // If cardinality is 1, we decrement to zero by removing the element from the set. 128 | if card = 1u then 129 | Map.remove value set 130 | else 131 | Map.add value (card - 1u) set 132 | 133 | // 134 | [] 135 | let removeMany value count (set : Multiset<'T>) : Multiset<'T> = 136 | // Preconditions 137 | checkNonNull "set" set 138 | if count < 0 then 139 | argOutOfRange "count" "Cannot remove a negative number of elements from the set." 140 | 141 | match Map.tryFind value set with 142 | | None -> 143 | set 144 | | Some card -> 145 | // If cardinality is <= the specified number of copies of this element to remove, 146 | // remove the element from the set altogether. 147 | if card <= uint32 count then 148 | Map.remove value set 149 | else 150 | Map.add value (card - uint32 count) set 151 | 152 | // 153 | [] 154 | let removeAll value (set : Multiset<'T>) : Multiset<'T> = 155 | // Preconditions 156 | checkNonNull "set" set 157 | 158 | Map.remove value set 159 | -------------------------------------------------------------------------------- /ExtCore/Collections.PriorityQueue.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | // 20 | namespace ExtCore.Collections 21 | 22 | open LanguagePrimitives 23 | open OptimizedClosures 24 | open ExtCore 25 | 26 | #nowarn "25" 27 | 28 | (* TODO : Implement modifications for global root, data bootstrapping, and other optimizations. *) 29 | (* TODO : Extract code for Brodal-Okasaki meldable heaps from the Coq theories here: 30 | https://code.google.com/p/priority-queues/ *) 31 | 32 | (* 33 | // TODO : Tag this with a unit-of-measure. 34 | type Rank = int 35 | 36 | type Tree<'T when 'T : comparison> = 37 | Node of 'T * Rank * Tree<'T> list 38 | 39 | (* auxiliary functions *) 40 | 41 | // 42 | [] 43 | module SkewBinomialQueue = 44 | type T<'T when 'T : comparison> = Tree<'T> list 45 | 46 | let root (Node (x,r,c)) = x 47 | let rank (Node (x,r,c)) = r 48 | 49 | let link (t1, t2) = 50 | match t1, t2 with 51 | | Node (x1, r1, c1), Node (x2, r2, c2) 52 | when r1 = r2 -> 53 | if x1 <= x2 then 54 | Node (x1, r1 + 1, t2 :: c1) 55 | else 56 | Node (x2, r2 + 1, t1 :: c2) 57 | | _ -> 58 | raise <| System.ArgumentException "The rank of both nodes must be the same." 59 | 60 | let skewLink ((Node (x0, r0, c0) as t0), (Node (x1, r1, c1) as t1), (Node (x2, r2, c2) as t2)) = 61 | if x1 <= x0 && x1 <= x2 then 62 | Node (x1, r1 + 1, t0 :: t2 :: c1) 63 | elif x2 <= x0 && x2 <= x1 then 64 | Node (x2, r2 + 1, t0 :: t1 :: c2) 65 | else 66 | Node (x0, r1 + 1, [t1; t2]) 67 | 68 | let rec ins = function 69 | | t, [] -> [t] 70 | | t, t' :: ts -> 71 | // rank t <= rank t' 72 | if rank t < rank t' then 73 | t :: t' :: ts 74 | else 75 | ins (link (t, t'), ts) 76 | 77 | let uniqify = function 78 | | [] -> [] 79 | | t :: ts -> 80 | // eliminate initial duplicate 81 | ins (t, ts) 82 | 83 | let rec meldUniq = function 84 | | [], ts 85 | | ts, [] -> 86 | ts 87 | | t1 :: ts1, t2 :: ts2 -> 88 | if rank t1 < rank t2 then 89 | t1 :: meldUniq (ts1, t2 :: ts2) 90 | elif rank t2 < rank t1 then 91 | t2 :: meldUniq (t1 :: ts1, ts2) 92 | else 93 | ins (link (t1, t2), meldUniq (ts1, ts2)) 94 | 95 | let empty = [] 96 | 97 | let isEmpty ts = List.isEmpty ts 98 | 99 | let insert x = function 100 | | t1 :: t2 :: rest as ts -> 101 | if rank t1 = rank t2 then 102 | skewLink (Node (x, 0, []), t1, t2) :: rest 103 | else 104 | Node (x, 0, []) :: ts 105 | | ts -> 106 | Node (x, 0, []) :: ts 107 | 108 | let meld (ts, ts') = 109 | meldUniq (uniqify ts, uniqify ts') 110 | 111 | exception EMPTY 112 | 113 | let rec findMin = function 114 | | [] -> 115 | raise EMPTY 116 | | [t] -> 117 | root t 118 | | t :: ts -> 119 | let x = findMin ts 120 | let rt = root t 121 | if rt <= x then rt else x 122 | 123 | let deleteMin = function 124 | | [] -> 125 | raise EMPTY 126 | | ts -> 127 | let rec getMin = function 128 | | [] -> 129 | invalidArg "ts" "The tree list is empty." 130 | | [t] -> 131 | t, [] 132 | | t :: ts -> 133 | let t', ts' = getMin ts 134 | if root t <= root t' then 135 | t, ts 136 | else 137 | t', t :: ts' 138 | 139 | let rec split = function 140 | | (ts, xs, []) -> 141 | ts, xs 142 | | (ts, xs, t :: c) -> 143 | if rank t = 0 then 144 | split (ts, root t :: xs, c) 145 | else 146 | split (t :: ts, xs, c) 147 | 148 | let (Node (x,r,c), ts) = getMin ts 149 | let ts', xs' = split ([], [], c) 150 | List.foldBack insert xs' (meld (ts, ts')) 151 | 152 | // 153 | [] 154 | module AddRoot = 155 | module Q = SkewBinomialQueue 156 | 157 | type T<'T when 'T : comparison> = 158 | | Empty 159 | | Root of 'T * Q.T<'T> 160 | 161 | // 162 | [] 163 | let empty<'T when 'T : comparison> : T<'T> = 164 | Empty 165 | 166 | // 167 | let isEmpty = function 168 | | Empty -> true 169 | | _ -> false 170 | 171 | // 172 | let insert y = function 173 | | Empty -> 174 | Root (y, Q.empty) 175 | | Root (x, q) -> 176 | if y <= x then 177 | Root (y, Q.insert x q) 178 | else 179 | Root (x, Q.insert y q) 180 | 181 | // 182 | let meld = function 183 | | Empty, rq 184 | | rq, Empty -> 185 | rq 186 | | Root (x1, q1), Root (x2, q2) -> 187 | if x1 <= x2 then 188 | Root (x1, Q.insert x2 <| Q.meld (q1, q2)) 189 | else 190 | Root (x2, Q.insert x1 <| Q.meld (q1, q2)) 191 | 192 | exception EMPTY 193 | 194 | let findMin = function 195 | | Root (x, _) -> x 196 | | Empty -> 197 | raise EMPTY 198 | 199 | let deleteMin = function 200 | | Empty -> 201 | raise EMPTY 202 | | Root (x, q) -> 203 | if Q.isEmpty q then Empty 204 | else 205 | Root (Q.findMin q, Q.deleteMin q) 206 | *) 207 | (* 208 | // 209 | [] 210 | module Bootstrap = 211 | module Q = SkewBinomialQueue 212 | 213 | // 214 | type Root<'T when 'T : comparison> = 215 | Root of 'T * Q.T<'T> 216 | 217 | // 218 | type T<'T when 'T : comparison> = 219 | | Empty 220 | | NonEmpty of Root<'T> 221 | 222 | // 223 | [] 224 | let empty<'T when 'T : comparison> : T<'T> = 225 | Empty 226 | 227 | // 228 | let isEmpty = function 229 | | Empty -> true 230 | | _ -> false 231 | 232 | // 233 | let rec meld = function 234 | | Empty, xs 235 | | xs, Empty -> 236 | xs 237 | | NonEmpty (Root (x1, q1) as r1), NonEmpty (Root (x2, q2) as r2) -> 238 | if x1 <= x2 then 239 | NonEmpty (Root (x1, Q.insert r2 q1)) 240 | else 241 | NonEmpty (Root (x2, Q.insert r1 q2)) 242 | 243 | // 244 | let insert (x, xs) = 245 | meld (NonEmpty (Root (x, Q.empty)), xs) 246 | 247 | exception EMPTY 248 | 249 | let findMin = function 250 | | Empty -> 251 | raise EMPTY 252 | | NonEmpty (Root (x, q)) -> x 253 | 254 | let deleteMin = function 255 | | Empty -> 256 | raise EMPTY 257 | | NonEmpty (Root (x, q)) -> 258 | if Q.isEmpty q then Empty 259 | else 260 | let (Root (y, q1)) = Q.findMin q 261 | let q2 = Q.deleteMin q 262 | NonEmpty (Root (y, Q.meld (q1, q2))) 263 | 264 | 265 | type Rank = uint32 266 | 267 | // 268 | type Tree<'T when 'T : comparison> = { 269 | // 270 | Value : 'T; 271 | // // 272 | // Forest : Tree<'T> list; 273 | // 274 | Children : Tree<'T> list; 275 | // 276 | Rank : Rank; 277 | } 278 | 279 | *) 280 | 281 | -------------------------------------------------------------------------------- /ExtCore/Collections.TaggedArray.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore.Collections 21 | 22 | open LanguagePrimitives 23 | open OptimizedClosures 24 | open ExtCore 25 | 26 | 27 | #if PROTO_COMPILER 28 | // TODO : Re-implement this module using the F# proto compiler, as in the TagMap and TagSet modules. 29 | // This will avoid the need to create "concrete" implementations of these functions, as we'll be able 30 | // to simply re-use existing implementations for the standard array type. 31 | [] 32 | module TaggedArray = 33 | /// Similar to Array.mapi, but 'tags' the index values with a unit-of-measure 34 | /// type before applying them to the mapping function. 35 | [] 36 | let mapi (mapping : int<'Tag> -> 'T -> 'U) (array : 'T[]) : 'U[] = 37 | // Preconditions 38 | checkNonNull "array" array 39 | 40 | let mapping = FSharpFunc<_,_,_>.Adapt mapping 41 | let len = array.Length 42 | let results = Array.zeroCreate len 43 | for i = 0 to len - 1 do 44 | results.[i] <- mapping.Invoke (Int32WithMeasure<'Tag> i, array.[i]) 45 | results 46 | 47 | /// Similar to Array.mapi, but 'tags' the index values with a unit-of-measure 48 | /// type before applying them to the mapping function. 49 | [] 50 | let mapi2 (mapping : int<'Tag> -> 'T1 -> 'T2 -> 'U) (array1 : 'T1[]) (array2 : 'T2[]) : 'U[] = 51 | // Preconditions 52 | checkNonNull "array1" array1 53 | checkNonNull "array2" array2 54 | 55 | let mapping = FSharpFunc<_,_,_,_>.Adapt mapping 56 | let len1 = array1.Length 57 | if len1 <> array2.Length then 58 | invalidArg "array2" "The arrays have differing lengths." 59 | 60 | let results = Array.zeroCreate len1 61 | for i = 0 to len1 - 1 do 62 | results.[i] <- mapping.Invoke (Int32WithMeasure<'Tag> i, array1.[i], array2.[i]) 63 | results 64 | 65 | /// Applies a function to each element of the collection, threading an accumulator argument through the computation. 66 | /// The integer index passed to the function indicates the array index of the element being transformed. 67 | /// The index values are tagged with a unit-of-measure type before applying them to the folder function. 68 | [] 69 | let foldi (folder : int<'Tag> -> 'State -> 'T -> 'State) (state : 'State) (array : 'T[]) : 'State = 70 | // Preconditions 71 | checkNonNull "array" array 72 | 73 | let folder = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt folder 74 | let mutable state = state 75 | let len = Array.length array 76 | for i = 0 to len - 1 do 77 | state <- folder.Invoke (Int32WithMeasure<'Tag> i, state, array.[i]) 78 | state 79 | 80 | /// Applies a function to each element of the collection, threading an accumulator argument through the computation. 81 | /// The integer index passed to the function indicates the array index of the element being transformed. 82 | /// The index values are tagged with a unit-of-measure type before applying them to the folder function. 83 | [] 84 | let foldiBack (folder : int<'Tag> -> 'T -> 'State -> 'State) (array : 'T[]) (state : 'State) : 'State = 85 | // Preconditions 86 | checkNonNull "array" array 87 | 88 | let folder = FSharpFunc<_,_,_,_>.Adapt folder 89 | 90 | let mutable state = state 91 | for i = Array.length array - 1 downto 0 do 92 | state <- folder.Invoke (Int32WithMeasure<'Tag> i, array.[i], state) 93 | state 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /ExtCore/Collections.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore.Collections 21 | 22 | open LanguagePrimitives 23 | open OptimizedClosures 24 | open ExtCore 25 | 26 | 27 | /// 28 | /// 29 | /// 30 | /// 31 | type IMapFolder<'State, 'Key, 'T> = 32 | /// 33 | /// 34 | /// 35 | abstract Map : key:'Key -> 'T 36 | 37 | /// 38 | /// 39 | /// 40 | /// 41 | abstract Fold : state:'State -> value:'T -> 'State 42 | 43 | // 44 | [] 45 | module MapFolder = 46 | /// 47 | /// 48 | /// 49 | /// 50 | [] 51 | let inline fromFunctions (mapping : 'Key -> 'T) (folder : 'State -> 'T -> 'State) = 52 | { new IMapFolder<'State, 'Key, 'T> with 53 | member __.Map (key : 'Key) : 'T = 54 | mapping key 55 | member __.Fold (state : 'State) (value : 'T) : 'State = 56 | folder state value } 57 | 58 | /// 59 | /// 60 | /// 61 | /// 62 | [] 63 | let inline fromFunctionsTupled (mapping : 'Key -> 'T) (folder : 'State * 'T -> 'State) = 64 | { new IMapFolder<'State, 'Key, 'T> with 65 | member __.Map (key : 'Key) : 'T = 66 | mapping key 67 | member __.Fold (state : 'State) (value : 'T) : 'State = 68 | folder (state, value) } 69 | 70 | 71 | /// 72 | /// 73 | /// 74 | type IMapReduction<'Key, 'T> = 75 | /// 76 | /// 77 | /// 78 | abstract Map : key:'Key -> 'T 79 | 80 | /// 81 | /// 82 | /// 83 | /// 84 | abstract Reduce : value1:'T -> value2:'T -> 'T 85 | 86 | // 87 | [] 88 | module MapReduction = 89 | /// 90 | /// 91 | /// 92 | /// 93 | [] 94 | let inline fromFunctions (mapping : 'Key -> 'T) (reduction : 'T -> 'T -> 'T) = 95 | { new IMapReduction<'Key, 'T> with 96 | member __.Map (key : 'Key) : 'T = 97 | mapping key 98 | member __.Reduce (value1 : 'T) (value2 : 'T) : 'T = 99 | reduction value1 value2 } 100 | 101 | /// 102 | /// 103 | /// 104 | /// 105 | [] 106 | let inline fromFunctionsTupled (mapping : 'Key -> 'T) (reduction : 'T * 'T -> 'T) = 107 | { new IMapReduction<'Key, 'T> with 108 | member __.Map (key : 'Key) : 'T = 109 | mapping key 110 | member __.Reduce (value1 : 'T) (value2 : 'T) : 'T = 111 | reduction (value1, value2) } 112 | 113 | 114 | /// Functional operators over a range of values. 115 | [] 116 | module Range = 117 | open LanguagePrimitives 118 | 119 | (* NOTE : In the functions below, 'start' and 'finish' are *inclusive*, just like the F# 'for' loop. *) 120 | 121 | /// 122 | /// 123 | /// 124 | /// 125 | /// 126 | [] 127 | let inline iter (action : ^T -> unit) start finish : unit = 128 | let mutable index = start 129 | while index <= finish do 130 | action index 131 | index <- index + GenericOne 132 | 133 | /// 134 | /// 135 | /// 136 | /// 137 | /// 138 | /// 139 | [] 140 | let inline fold (folder : ^State -> ^T -> ^State) start finish state : ^State = 141 | let mutable state = state 142 | let mutable index = start 143 | while index <= finish do 144 | state <- folder state index 145 | index <- index + GenericOne 146 | state 147 | 148 | /// 149 | /// 150 | /// 151 | /// 152 | /// 153 | /// 154 | [] 155 | let inline foldBack (folder : ^T -> ^State -> ^State) start finish state : ^State = 156 | let mutable state = state 157 | let mutable index = finish 158 | while index >= start do 159 | state <- folder index state 160 | index <- index - GenericOne 161 | state 162 | 163 | /// 164 | /// 165 | /// 166 | /// 167 | /// 168 | [] 169 | let inline exists (predicate : ^T -> bool) start finish : bool = 170 | let mutable foundMatch = false 171 | let mutable index = start 172 | while index <= finish && not foundMatch do 173 | foundMatch <- predicate index 174 | index <- index + GenericOne 175 | foundMatch 176 | 177 | /// 178 | /// 179 | /// 180 | /// 181 | /// 182 | [] 183 | let inline forall (predicate : ^T -> bool) start finish : bool = 184 | let mutable allMatch = true 185 | let mutable index = start 186 | while index <= finish && allMatch do 187 | allMatch <- predicate index 188 | index <- index + GenericOne 189 | allMatch 190 | 191 | // TODO 192 | // mapReduce 193 | 194 | 195 | /// 196 | /// Functional programming operators related to the type. 197 | /// 198 | [] 199 | module KeyValuePair = 200 | open System.Collections.Generic 201 | 202 | /// Gets the key from the key/value pair. 203 | [] 204 | let inline key (kvp : KeyValuePair<'Key, 'T>) = 205 | kvp.Key 206 | 207 | /// Gets the value in the key/value pair. 208 | [] 209 | let inline value (kvp : KeyValuePair<'Key, 'T>) = 210 | kvp.Value 211 | 212 | /// 213 | /// Transforms the value in a key/value pair by applying the specified function to it. The key passed to the function 214 | /// indicates the key of the value being transformed. This function is analogous to . 215 | /// 216 | [] 217 | let map (mapping : 'Key -> 'T -> 'U) (kvp : KeyValuePair<'Key, 'T>) : KeyValuePair<'Key, 'U> = 218 | KeyValuePair (kvp.Key, mapping kvp.Key kvp.Value) 219 | 220 | -------------------------------------------------------------------------------- /ExtCore/Control.Observable.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2011 Tomas Petricek 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore.Control 21 | 22 | open ExtCore 23 | open System 24 | open System.Threading 25 | 26 | #if FX_ATLEAST_45 27 | open System.Runtime.ExceptionServices 28 | #endif 29 | 30 | #nowarn "40" 31 | 32 | 33 | /// 34 | /// Union type that represents different messages that can be sent to the interface. 35 | /// The IObserver type is equivalent to a type that only exposes an OnNext method accepting an instance of 36 | /// as an argument. 37 | /// 38 | /// The notification argument type. 39 | /// 40 | /// This type essentially replicates the functionality of the type 41 | /// found in the Reactive Extensions (Rx.NET) library. 42 | /// 43 | [] 44 | [] 45 | type Notification<'T> = 46 | // 47 | | Completed 48 | // 49 | | Next of 'T 50 | // 51 | | Error of exn 52 | 53 | // 54 | [] 55 | module Observable = 56 | open ExtCore.Control.Agents 57 | 58 | /// Returns an observable that yields sliding windows of 59 | /// containing elements drawn from the input observable. 60 | /// Each window is returned as a fresh array. 61 | [] 62 | let windowed size (input : IObservable<'T>) = 63 | // Preconditions 64 | if size < 1 then 65 | argOutOfRange "size" "The window size must be greater than zero (0)." 66 | checkNonNull "input" input 67 | 68 | { new IObservable<'T[]> with 69 | member x.Subscribe observer = 70 | // Create sliding window agent for every call 71 | // and redirect batches to the observer 72 | let cts = new CancellationTokenSource () 73 | let agent = SlidingWindowAgent<_> (size, cts.Token) 74 | agent.WindowProduced.Add observer.OnNext 75 | 76 | // Subscribe to the input and send values to the agent 77 | let subscription = 78 | { new IObserver<'T> with 79 | member __.OnNext v = 80 | agent.Enqueue v 81 | member __.OnCompleted () = 82 | cts.Cancel () 83 | observer.OnCompleted () 84 | member __.OnError e = 85 | cts.Cancel () 86 | observer.OnError e } 87 | |> input.Subscribe 88 | 89 | // Cancel subscription & cancel the agent 90 | { new IDisposable with 91 | member x.Dispose () = 92 | subscription.Dispose () 93 | cts.Cancel () } } 94 | 95 | /// Creates an observable that calls the specified function (each time) 96 | /// after an observer is attached to the observable. This is useful to 97 | /// make sure that events triggered by the function are handled. 98 | [] 99 | let guard action (input : IObservable<'Args>) = 100 | // Preconditions 101 | checkNonNull "input" input 102 | 103 | { new IObservable<'Args> with 104 | member x.Subscribe observer = 105 | let rm = input.Subscribe observer 106 | action () 107 | rm } 108 | 109 | /// Turns observable into an observable that only calls OnNext method of the 110 | /// observer, but gives it a discriminated union that represents different 111 | /// kinds of events (error, next, completed) 112 | [] 113 | let asUpdates (input : IObservable<'T>) = 114 | // Preconditions 115 | checkNonNull "input" input 116 | 117 | { new IObservable<_> with 118 | member x.Subscribe observer = 119 | { new IObserver<_> with 120 | member x.OnNext v = 121 | observer.OnNext (Next v) 122 | member x.OnCompleted () = 123 | observer.OnNext(Completed) 124 | member x.OnError e = 125 | observer.OnNext (Error e) } 126 | |> input.Subscribe } 127 | 128 | 129 | // 130 | [] 131 | module ObservableExtensions = 132 | /// Helper that can be used for writing CPS-style code that resumes 133 | /// on the same thread where the operation was started. 134 | let internal synchronize f = 135 | let ctx = System.Threading.SynchronizationContext.Current 136 | f <| fun g -> 137 | let nctx = System.Threading.SynchronizationContext.Current 138 | if ctx <> null && ctx <> nctx then 139 | ctx.Post ((fun _ -> g ()), null) 140 | else g () 141 | 142 | type Microsoft.FSharp.Control.Async with 143 | /// Behaves like AwaitObservable, but calls the specified guarding function 144 | /// after a subscriber is registered with the observable. 145 | static member GuardedAwaitObservable (ev1 : IObservable<'T1>) guardFunction = 146 | // Preconditions 147 | checkNonNull "ev1" ev1 148 | 149 | synchronize <| fun f -> 150 | Async.FromContinuations <| fun (cont, econt, ccont) -> 151 | let rec finish cont value = 152 | remover.Dispose () 153 | f (fun () -> cont value) 154 | 155 | and remover : IDisposable = 156 | { new IObserver<_> with 157 | member x.OnNext v = 158 | finish cont v 159 | member x.OnError e = 160 | finish econt e 161 | member x.OnCompleted () = 162 | let msg = "Cancelling the workflow, because the Observable awaited using AwaitObservable has completed." 163 | finish ccont (System.OperationCanceledException msg) } 164 | |> ev1.Subscribe 165 | 166 | guardFunction () 167 | 168 | /// Creates an asynchronous workflow that will be resumed when the specified observables produces a value. 169 | /// The workflow will return the value produced by the observable. 170 | static member AwaitObservable (ev1 : IObservable<'T1>) = 171 | // Preconditions 172 | checkNonNull "ev1" ev1 173 | 174 | synchronize <| fun f -> 175 | Async.FromContinuations <| fun (cont, econt, ccont) -> 176 | let rec finish cont value = 177 | remover.Dispose () 178 | f (fun () -> cont value) 179 | 180 | and remover : IDisposable = 181 | { new IObserver<_> with 182 | member x.OnNext v = 183 | finish cont v 184 | member x.OnError e = 185 | finish econt e 186 | member x.OnCompleted () = 187 | let msg = "Cancelling the workflow, because the Observable awaited using AwaitObservable has completed." 188 | finish ccont (System.OperationCanceledException msg) } 189 | |> ev1.Subscribe 190 | 191 | // Explicitly return the unit value here to make this an expression and satisfy the compiler. 192 | () 193 | 194 | /// Creates an asynchronous workflow that will be resumed when the first of the specified 195 | /// two observables produces a value. The workflow will return a Choice value that can be 196 | /// used to identify the observable that produced the value. 197 | static member AwaitObservable (ev1 : IObservable<'T1>, ev2 : IObservable<'T2>) = 198 | // Preconditions 199 | checkNonNull "ev1" ev1 200 | checkNonNull "ev2" ev2 201 | 202 | [ ev1 |> Observable.map Choice1Of2; 203 | ev2 |> Observable.map Choice2Of2; ] 204 | |> List.reduce Observable.merge 205 | |> Async.AwaitObservable 206 | 207 | /// Creates an asynchronous workflow that will be resumed when the first of the specified 208 | /// three observables produces a value. The workflow will return a Choice value that can be 209 | /// used to identify the observable that produced the value. 210 | static member AwaitObservable (ev1 : IObservable<'T1>, ev2 : IObservable<'T2>, ev3 : IObservable<'T3>) = 211 | // Preconditions 212 | checkNonNull "ev1" ev1 213 | checkNonNull "ev2" ev2 214 | checkNonNull "ev3" ev3 215 | 216 | [ ev1 |> Observable.map Choice1Of3; 217 | ev2 |> Observable.map Choice2Of3; 218 | ev3 |> Observable.map Choice3Of3; ] 219 | |> List.reduce Observable.merge 220 | |> Async.AwaitObservable 221 | 222 | /// Creates an asynchronous workflow that will be resumed when the first of the specified 223 | /// four observables produces a value. The workflow will return a Choice value that can be 224 | /// used to identify the observable that produced the value. 225 | static member AwaitObservable (ev1 : IObservable<'T1>, ev2 : IObservable<'T2>, ev3 : IObservable<'T3>, ev4 : IObservable<'T4>) = 226 | // Preconditions 227 | checkNonNull "ev1" ev1 228 | checkNonNull "ev2" ev2 229 | checkNonNull "ev3" ev3 230 | checkNonNull "ev4" ev4 231 | 232 | [ ev1 |> Observable.map Choice1Of4; 233 | ev2 |> Observable.map Choice2Of4; 234 | ev3 |> Observable.map Choice3Of4; 235 | ev4 |> Observable.map Choice4Of4; ] 236 | |> List.reduce Observable.merge 237 | |> Async.AwaitObservable 238 | 239 | -------------------------------------------------------------------------------- /ExtCore/Control.Tasks.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2014 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace ExtCore.Control.Tasks 20 | 21 | open System.Threading.Tasks 22 | open ExtCore 23 | 24 | 25 | /// 26 | /// 27 | [] 28 | type TaskBuilder () = 29 | // 'T -> M<'T> 30 | member inline __.Return value 31 | : Task<'T> = 32 | #if FX_ATLEAST_45 33 | Task.FromResult<'T> (value) 34 | #else 35 | new Task<'T> (fun () -> value) 36 | #endif 37 | 38 | // M<'T> -> M<'T> 39 | member inline __.ReturnFrom task 40 | : Task<'T> = 41 | task 42 | 43 | // unit -> M<'T> 44 | member inline this.Zero () 45 | : Task = 46 | this.Return () 47 | 48 | // (unit -> M<'T>) -> M<'T> 49 | member __.Delay (taskThunk : unit -> Task<'T>) 50 | : Task<'T> = 51 | new Task<'T>(fun () -> 52 | // Execute the task thunk to create the task. 53 | let task = taskThunk () 54 | 55 | // Run the delayed task synchronously. 56 | task.RunSynchronously () 57 | task.Wait () 58 | 59 | // Return the result of the task. 60 | task.Result) 61 | 62 | // M<'T> * ('T -> M<'U>) -> M<'U> 63 | member __.Bind (task : Task<'T>, binder : 'T -> Task<'U>) 64 | : Task<'U> = 65 | task.ContinueWith<'U>(fun (task : Task<'T>) -> 66 | // Apply the result from 'task' to the binder function to create a new task. 67 | let childTask = binder task.Result 68 | 69 | // Run the child task synchronously, then return it's result. 70 | childTask.RunSynchronously () 71 | childTask.Result) 72 | 73 | // M<'T> -> M<'T> -> M<'T> 74 | // or 75 | // M -> M<'T> -> M<'T> 76 | member __.Combine (task1 : Task, task2 : Task<'T>) 77 | : Task<'T> = 78 | task1.ContinueWith<'T> (fun (_ : Task) -> 79 | // Run 'task2' synchronously, then return it's result. 80 | task2.RunSynchronously () 81 | task2.Result) 82 | 83 | // M<'T> * (exn -> M<'T>) -> M<'T> 84 | member __.TryWith (body : Task<'T>, handler : System.AggregateException -> Task<'T>) 85 | : Task<'T> = 86 | new Task<'T>(fun () -> 87 | try 88 | // Run the body task. 89 | body.RunSynchronously () 90 | body.Wait () 91 | 92 | // Return the result from the body task. 93 | body.Result 94 | with :? System.AggregateException as ae -> 95 | // Create the handler task from the handler function. 96 | let handlerTask = handler ae 97 | 98 | // Run the handler task. 99 | handlerTask.RunSynchronously () 100 | handlerTask.Wait () 101 | 102 | // Return the result from the handler task. 103 | handlerTask.Result) 104 | 105 | // M<'T> * (unit -> unit) -> M<'T> 106 | member __.TryFinally (body : Task<'T>, handler : unit -> unit) 107 | : Task<'T> = 108 | new Task<'T>(fun () -> 109 | try 110 | // Run the body task. 111 | body.RunSynchronously () 112 | body.Wait () 113 | 114 | // Return the result from the body task. 115 | body.Result 116 | finally 117 | // Run the handler function. 118 | handler ()) 119 | 120 | // 'T * ('T -> M<'U>) -> M<'U> when 'T :> IDisposable 121 | member this.Using (resource : ('T :> System.IDisposable), binding : 'T -> Task<'U>) 122 | : Task<'U> = 123 | let body = new Task<_>(fun () -> 124 | // Apply the resource to the binding function to create a new task 125 | // (which presumably uses the resource). 126 | let task = binding resource 127 | 128 | // Run the task. 129 | task.RunSynchronously () 130 | task.Wait () 131 | 132 | // Return the result from the task. 133 | task.Result) 134 | this.TryFinally (body, (fun () -> 135 | if not <| isNull (box resource) then 136 | resource.Dispose ())) 137 | 138 | // (unit -> bool) * M<'T> -> M<'T> 139 | member this.While (guard, body : Task<_>) 140 | : Task = 141 | if guard () then 142 | this.Bind (body, (fun () -> this.While (guard, body))) 143 | else 144 | this.Zero () 145 | 146 | // seq<'T> * ('T -> M<'U>) -> M<'U> 147 | // or 148 | // seq<'T> * ('T -> M<'U>) -> seq> 149 | member this.For (sequence : seq<_>, body : 'T -> Task<_>) 150 | : Task = 151 | this.Using (sequence.GetEnumerator (), fun enum -> 152 | this.While ( 153 | enum.MoveNext, 154 | this.Delay (fun () -> 155 | body enum.Current))) 156 | 157 | /// 158 | /// 159 | [] 160 | module WorkflowBuilders = 161 | // 162 | [] 163 | let tasks = TaskBuilder () 164 | 165 | -------------------------------------------------------------------------------- /ExtCore/ControlCollections.AsyncProtectedState.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2013 Jack Pappas 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | // 20 | [] 21 | module ExtCore.Control.Collections.AsyncProtectedState 22 | 23 | open OptimizedClosures 24 | open ExtCore 25 | open ExtCore.Collections 26 | open ExtCore.Control 27 | 28 | (* TODO : Implement the AsyncProtectedState collections. *) 29 | -------------------------------------------------------------------------------- /ExtCore/ControlCollections.Cont.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | // 21 | [] 22 | module ExtCore.Control.Collections.Cps.Cont 23 | 24 | open Microsoft.FSharp.Control 25 | open OptimizedClosures 26 | open ExtCore 27 | open ExtCore.Collections 28 | open ExtCore.Control.Cps 29 | 30 | 31 | /// The standard F# Array module, adapted for use within 'cont' workflows. 32 | [] 33 | module Array = 34 | /// Cont implementation of Array.fold. 35 | let rec private foldImpl (folder : FSharpFunc<_,_,_>, array : 'T[], state : 'State, currentIndex) : ContFunc<'State, 'K> = 36 | cont { 37 | if currentIndex >= array.Length then 38 | // We've reached the end of the array so return the final state value. 39 | return state 40 | else 41 | // Invoke the folder with the current array element and state value. 42 | let! state = folder.Invoke (state, array.[currentIndex]) 43 | 44 | // Continue folding over the remaining array elements. 45 | return! foldImpl (folder, array, state, currentIndex + 1) 46 | } 47 | 48 | /// Cont implementation of Array.fold. 49 | [] 50 | let fold (folder : 'State -> 'T -> ContFunc<'State, 'K>) (state : 'State) (array : 'T[]) : ContFunc<'State, 'K> = 51 | // Preconditions 52 | checkNonNull "array" array 53 | 54 | // Call the recursive implementation. 55 | let folder = FSharpFunc<_,_,_>.Adapt folder 56 | foldImpl (folder, array, state, 0) 57 | 58 | 59 | /// The standard F# List module, adapted for use within 'cont' workflows. 60 | [] 61 | module List = 62 | /// Cont implementation of List.fold. 63 | let rec private foldImpl (folder : FSharpFunc<_,_,_>, list : 'T list, state : 'State) : ContFunc<'State, 'K> = 64 | cont { 65 | match list with 66 | | [] -> 67 | // We've reached the end of the list so return the final state value. 68 | return state 69 | | hd :: tl -> 70 | // Invoke the folder with the head element of the list and the current state value. 71 | let! state = folder.Invoke (state, hd) 72 | 73 | // Continue folding over the rest of the list. 74 | return! foldImpl (folder, tl, state) 75 | } 76 | 77 | /// Cont implementation of List.fold. 78 | [] 79 | let fold (folder : 'State -> 'T -> ContFunc<'State, 'K>) (state : 'State) (list : 'T list) : ContFunc<'State, 'K> = 80 | // Preconditions 81 | checkNonNull "list" list 82 | 83 | // Call the recursive implementation. 84 | let folder = FSharpFunc<_,_,_>.Adapt folder 85 | foldImpl (folder, list, state) 86 | 87 | -------------------------------------------------------------------------------- /ExtCore/ControlCollections.StateCont.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | // 21 | [] 22 | module ExtCore.Control.Collections.Cps.StateCont 23 | 24 | open Microsoft.FSharp.Control 25 | open OptimizedClosures 26 | open ExtCore 27 | open ExtCore.Collections 28 | open ExtCore.Control.Cps 29 | 30 | 31 | /// The standard F# Array module, adapted for use within 'stateCont' workflows. 32 | [] 33 | module Array = 34 | /// StateCont implementation of Array.map. 35 | let rec private mapImpl mapping (results : 'U[]) (array : 'T[]) currentIndex : StateContFunc<'State, 'U[], 'K> = 36 | stateCont { 37 | if currentIndex >= array.Length then 38 | // Return the mapped array and the final state value. 39 | return results 40 | else 41 | // Map the current array element, then store the result into the results array. 42 | let! result = mapping array.[currentIndex] 43 | results.[currentIndex] <- result 44 | 45 | // Map the remaining elements. 46 | return! mapImpl mapping results array (currentIndex + 1) 47 | } 48 | 49 | /// StateCont implementation of Array.map. 50 | [] 51 | let map (mapping : 'T -> StateContFunc<'State, 'U, 'K>) (array : 'T[]) : StateContFunc<'State, 'U[], 'K> = 52 | // Preconditions 53 | checkNonNull "array" array 54 | 55 | let result = Array.zeroCreate <| Array.length array 56 | 57 | // Call the recursive implementation. 58 | mapImpl mapping result array 0 59 | 60 | /// StateCont implementation of Array.mapi. 61 | let rec private mapiImpl mapping (results : 'U[]) (array : 'T[]) currentIndex : StateContFunc<'State, 'U[], 'K> = 62 | stateCont { 63 | if currentIndex >= array.Length then 64 | // Return the mapped array and the final state value. 65 | return results 66 | else 67 | // Map the current array element, then store the result into the results array. 68 | let! result = mapping currentIndex array.[currentIndex] 69 | results.[currentIndex] <- result 70 | 71 | // Map the remaining elements. 72 | return! mapiImpl mapping results array (currentIndex + 1) 73 | } 74 | 75 | /// StateCont implementation of Array.mapi. 76 | [] 77 | let mapi (mapping : int -> 'T -> StateContFunc<'State, 'U, 'K>) (array : 'T[]) : StateContFunc<'State, 'U[], 'K> = 78 | // Preconditions 79 | checkNonNull "array" array 80 | 81 | let result = Array.zeroCreate <| Array.length array 82 | 83 | // Call the recursive implementation. 84 | mapiImpl mapping result array 0 85 | 86 | -------------------------------------------------------------------------------- /ExtCore/ControlCollections.StatefulChoice.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | // 21 | [] 22 | module ExtCore.Control.Collections.StatefulChoice 23 | 24 | open Microsoft.FSharp.Control 25 | open OptimizedClosures 26 | open ExtCore 27 | open ExtCore.Collections 28 | 29 | 30 | /// The standard F# Array module, lifted into the StatefulChoice monad. 31 | [] 32 | module Array = 33 | /// A specialization of Array.map which threads an accumulator through the computation and which also 34 | /// short-circuits the computation if the mapping function returns an error when any element is applied to it. 35 | [] 36 | let map (mapping : 'T -> 'State -> Choice<'U, 'Error> * 'State) 37 | (array : 'T[]) (state : 'State) : Choice<'U[], 'Error> * 'State = 38 | // Preconditions 39 | checkNonNull "array" array 40 | 41 | let mapping = FSharpFunc<_,_,_>.Adapt mapping 42 | let len = Array.length array 43 | /// Holds the mapped results. 44 | let results = Array.zeroCreate len 45 | 46 | let mutable state = state 47 | let mutable error = None 48 | let mutable index = 0 49 | 50 | while index < len && Option.isNone error do 51 | let result, state' = mapping.Invoke (array.[index], state) 52 | 53 | // Update the state, even if the result was an error. 54 | state <- state' 55 | 56 | // Check the result; short-circuit if it's an error. 57 | match result with 58 | | Choice2Of2 err -> 59 | error <- Some err 60 | | Choice1Of2 result -> 61 | results.[index] <- result 62 | index <- index + 1 63 | 64 | // Return the updated state along with the 65 | // result (or error, if set). 66 | match error with 67 | | Some error -> 68 | (Choice2Of2 error), state 69 | | None -> 70 | (Choice1Of2 results), state 71 | 72 | -------------------------------------------------------------------------------- /ExtCore/ExtCore.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.6;netstandard2.0;net45 5 | ExtCore 6 | 0.8.47 7 | https://github.com/jack-pappas/ExtCore 8 | 0.8.47 9 | 0.8.47 10 | ExtCore provides extensions to the F# core library (FSharp.Core) and aims to help you build 11 | industrial-strength F# applications. These extensions include additional functions for modules such as 12 | Array, List, Set, and Map; immutable IntSet, IntMap, LazyList, and Queue collections; a variety of 13 | computation expressions (workflows); and "workflow collections" -- collections modules which have been 14 | adapted to work seamlessly from within workflows. 15 | 16 | Jack Pappas 17 | http://opensource.org/licenses/Apache-2.0 18 | https://github.com/jack-pappas/ExtCore 19 | f# fsharp workflow collections immutable workflow monad computation fsharpx intmap lazylist 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 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ExtCore/ExtraPervasives.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore 21 | 22 | 23 | /// Additional F# operators and types that are available without opening a module or namespace. 24 | [] 25 | module ExtraTopLevelOperators = 26 | open LanguagePrimitives 27 | open ExtCore.Collections 28 | 29 | /// Creates a tagged integer from an integer value. 30 | [] 31 | let inline tag<[] 'Tag> (value : int) : int<'Tag> = 32 | Int32WithMeasure value 33 | 34 | /// Removes the tag from a tagged integer, returning the integer value. 35 | [] 36 | let inline untag<[] 'Tag> (tag : int<'Tag>) : int = 37 | int tag 38 | 39 | /// Creates a tagged 64-bit integer from a 64-bit integer value. 40 | [] 41 | let inline tagl<[] 'Tag> (value : int64) : int64<'Tag> = 42 | Int64WithMeasure value 43 | 44 | /// Removes the tag from a tagged 64-bit integer, returning the 64-bit integer value. 45 | [] 46 | let inline untagl<[] 'Tag> (tag : int64<'Tag>) : int64 = 47 | int64 tag 48 | 49 | /// Builds a map from a sequence of key-value pairs. 50 | [] 51 | let inline map (elements : seq<_>) : Map<'Key, 'T> = 52 | Map (elements) 53 | 54 | /// Creates an immutable vector from an array. 55 | [] 56 | let inline vector (array : 'T[]) : vector<'T> = 57 | vector.Create array 58 | 59 | /// Builds a map from a sequence of key-value pairs. 60 | [] 61 | let inline intMap (elements : seq<_>) : IntMap<'T> = 62 | IntMap (elements) 63 | 64 | /// Builds a set from a sequence of elements. 65 | [] 66 | let inline intSet (elements : seq<_>) : IntSet = 67 | IntSet (elements) 68 | 69 | /// Builds a map from a sequence of key-value pairs. 70 | [] 71 | let inline longMap (elements : seq<_>) : LongMap<'T> = 72 | LongMap (elements) 73 | 74 | /// Builds a set from a sequence of elements. 75 | [] 76 | let inline longSet (elements : seq<_>) : LongSet = 77 | LongSet (elements) 78 | 79 | /// Builds a map from a sequence of key-value pairs. 80 | [] 81 | let inline hashMap (elements : seq<_>) : HashMap<'Key, 'T> = 82 | HashMap (elements) 83 | 84 | /// Builds a set from a sequence of elements. 85 | [] 86 | let inline hashSet (elements : seq<_>) : HashSet<'T> = 87 | HashSet (elements) 88 | 89 | /// Computation expression ("workflow") builder for creating lazy lists. 90 | [] 91 | let lazyList = LazyListBuilder () 92 | -------------------------------------------------------------------------------- /ExtCore/NativeInterop.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2010-2012 TidePowerd Ltd. 4 | Copyright 2013 Jack Pappas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | *) 19 | 20 | namespace ExtCore.NativeInterop 21 | 22 | open Microsoft.FSharp.NativeInterop 23 | 24 | #nowarn "9" // Disable warning about unverifiable IL 25 | 26 | 27 | /// Functions for working with native pointers. 28 | [] 29 | module NativePtr = 30 | /// The null pointer. 31 | //[] 32 | [] 33 | let zero<'T when 'T : unmanaged> : nativeptr<'T> = 34 | NativePtr.ofNativeInt 0n 35 | 36 | /// Determines if a pointer is null. 37 | [] 38 | let [] inline isNull (ptr : nativeptr<'T>) = 39 | 0n = NativePtr.toNativeInt ptr 40 | 41 | 42 | -------------------------------------------------------------------------------- /ExtCore/Net.fs: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Copyright 2011 Tomas Petricek 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | *) 18 | 19 | namespace ExtCore.Net 20 | 21 | #if FX_ATLEAST_PORTABLE || NETSTANDARD1_6 22 | #else 23 | 24 | open System 25 | open System.IO 26 | open System.Net 27 | open System.Text 28 | open System.Threading 29 | open ExtCore 30 | open ExtCore.Collections 31 | open ExtCore.IO 32 | 33 | /// Extensions that simplify working with HttpListener and related types. 34 | [] 35 | module HttpExtensions = 36 | type System.Net.HttpListener with 37 | /// Asynchronously waits for an incoming request and returns it. 38 | member this.AsyncGetContext () = 39 | Async.FromBeginEnd (this.BeginGetContext, this.EndGetContext) 40 | 41 | /// Starts HttpListener on the specified URL. The 'handler' function is 42 | /// called (in a new thread pool thread) each time an HTTP request is received. 43 | static member Start (url, handler, ?cancellationToken) = 44 | let server = 45 | async { 46 | use listener = new HttpListener () 47 | listener.Prefixes.Add url 48 | listener.Start () 49 | while true do 50 | let! context = listener.AsyncGetContext () 51 | let asyncHandler = handler (context.Request, context.Response) 52 | Async.Start (asyncHandler, ?cancellationToken = cancellationToken) 53 | } 54 | 55 | Async.Start (server, ?cancellationToken = cancellationToken) 56 | 57 | type System.Net.HttpListenerRequest with 58 | /// Asynchronously reads the 'InputStream' of the request and converts it to a string 59 | member this.AsyncInputString : Async = 60 | async { 61 | use tmp = new MemoryStream () 62 | for data in this.InputStream.AsyncReadSeq (16 * 1024) do 63 | tmp.Write (data, 0, data.Length) 64 | tmp.Seek (0L, SeekOrigin.Begin) |> ignore 65 | use sr = new StreamReader (tmp) 66 | return sr.ReadToEnd () 67 | } 68 | 69 | type System.Net.HttpListenerResponse with 70 | /// Sends the specified string as a reply in UTF-8 encoding 71 | member this.AsyncReply (str : string) = 72 | // Preconditions 73 | checkNonNull "str" str 74 | 75 | async { 76 | let buffer = Encoding.UTF8.GetBytes str 77 | this.ContentLength64 <- int64 buffer.Length 78 | let output = this.OutputStream 79 | do! output.AsyncWrite (buffer, 0, buffer.Length) 80 | output.Close () 81 | } 82 | 83 | /// Sends the specified data as a reply with the specified content type 84 | member this.AsyncReply (contentType, buffer : byte[]) = 85 | // Preconditions 86 | //checkNonNull "contentType" contentType 87 | checkNonNull "buffer" buffer 88 | 89 | async { 90 | this.ContentLength64 <- int64 buffer.Length 91 | let output = this.OutputStream 92 | this.ContentType <- contentType 93 | do! output.AsyncWrite (buffer, 0, buffer.Length) 94 | output.Close () 95 | } 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | ExtCore 3 | ======= 4 | 5 | .. image:: https://travis-ci.org/jack-pappas/ExtCore.png 6 | :target: https://travis-ci.org/jack-pappas/ExtCore 7 | 8 | .. image:: http://img.shields.io/nuget/v/ExtCore.svg 9 | :target: https://nuget.org/packages/ExtCore/ 10 | 11 | *ExtCore* is an extended core library for F#. *ExtCore* is designed to the same coding guidelines and quality standards as the F# core library (*FSharp.Core*), so the API is simple and intuitive to use. 12 | 13 | *ExtCore* **does not** aim to be a "batteries-included" library; instead, *ExtCore* functionality is concentrated into a few key areas: 14 | 15 | - *Pervasives* 16 | 17 | Top-level operators, functions, and modules providing common functionality. For example, the ``notImpl`` operator can be used to raise a ``System.NotImplementedException`` instead of the less-specific ``failwith``, and the ``Option`` module provides additional functions for working with the ``'T option`` type to complement those available in *FSharp.Core*'s ``Option`` module. 18 | 19 | - *Collections* 20 | 21 | Immutable data structures. Some of these are drop-in (almost) replacements for the ``Map`` and ``Set`` types in *FSharp.Core* which provide improved performance in specific scenarios (e.g., ``HashMap``). Others provide unique functionality to help tackle specific coding tasks (e.g., ``LazyList`` and ``LruCache``). 22 | 23 | - *Control* 24 | 25 | Computation expressions (a.k.a. "workflows" or "monads") aimed at simplifying the implementation of common functional programming patterns. For example, *ExtCore* provides an ``asyncMaybe`` workflow which is similar to ``async`` in *FSharp.Core* but includes additional logic to handle cases where a computation encounters an error or fails to return a valid result. 26 | 27 | - *Control.Collections* 28 | 29 | Modules which mirror the built-in collections modules in *FSharp.Core* like ``Array`` or ``Map``, but whose functions are designed to work with the computation expressions included in *ExtCore*. For example, you might have some code that uses the ``Array.map`` function; if your mapping function can sometimes fail, you can use the ``Choice.Array.map`` function instead to gracefully handle the error instead of raising an exception. 30 | 31 | 32 | Known Bugs/Issues 33 | ================= 34 | 35 | Known bugs or other issues are listed on the `ExtCore issues`_ page. 36 | 37 | .. _`ExtCore issues`: https://github.com/jack-pappas/ExtCore/issues 38 | 39 | 40 | Licensing 41 | ========= 42 | ExtCore is licensed under the terms of the `Apache 2.0 license`_. 43 | 44 | .. _`Apache 2.0 license`: https://www.apache.org/licenses/LICENSE-2.0.html 45 | -------------------------------------------------------------------------------- /_docs/Changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ######### 3 | 4 | `0.8.x (alpha)`_ 5 | The *0.8.x* (alpha) branch. 6 | 7 | 8 | 9 | 0.8.x (Alpha) 10 | ============= 11 | 12 | 0.8.30 (HEAD) 13 | -------------------- 14 | 15 | *TODO* 16 | 17 | 18 | 0.8.29 (2013-Jun-21) 19 | -------------------- 20 | 21 | *TODO* 22 | 23 | 24 | 0.8.28 (2013-Jun-14) 25 | -------------------- 26 | 27 | *TODO* 28 | 29 | 30 | 0.8.27 (2013-Jun-11) 31 | -------------------- 32 | 33 | *TODO* 34 | 35 | 36 | 0.8.26 (2013-Jun-10) 37 | -------------------- 38 | 39 | *TODO* 40 | 41 | 42 | 0.8.25 (2013-Jun-08) 43 | -------------------- 44 | 45 | *TODO* 46 | 47 | 48 | 0.8.24 (2013-Jun-05) 49 | -------------------- 50 | 51 | *TODO* 52 | 53 | 54 | 0.8.23 (2013-May-31) 55 | -------------------- 56 | 57 | *TODO* 58 | 59 | 60 | 0.8.22 (2013-May-31) 61 | -------------------- 62 | 63 | *TODO* 64 | 65 | 66 | 0.8.21 (2013-May-24) 67 | -------------------- 68 | 69 | *TODO* 70 | 71 | 72 | 0.8.20 (2013-May-19) 73 | -------------------- 74 | 75 | *TODO* 76 | 77 | 78 | 0.8.19 (2013-May-17) 79 | -------------------- 80 | 81 | *TODO* 82 | 83 | 84 | 0.8.18 (2013-May-17) 85 | -------------------- 86 | 87 | *ExtCore 0.8.18 was withdrawn due to a build issue.* 88 | 89 | 90 | 0.8.17 (2013-May-01) 91 | -------------------- 92 | 93 | *TODO* 94 | 95 | 96 | 0.8.16 (2013-Apr-26) 97 | -------------------- 98 | 99 | *TODO* 100 | 101 | 102 | 0.8.15 (2013-Apr-10) 103 | -------------------- 104 | 105 | *TODO* 106 | 107 | 108 | 0.8.14 (2013-Apr-08) 109 | -------------------- 110 | 111 | *TODO* 112 | 113 | 114 | 0.8.13 (2013-Apr-04) 115 | -------------------- 116 | 117 | *TODO* 118 | 119 | 120 | 0.8.12 (2013-Apr-04) 121 | -------------------- 122 | 123 | *TODO* 124 | 125 | 126 | 0.8.11 (2013-Apr-02) 127 | -------------------- 128 | 129 | *TODO* 130 | 131 | 132 | 0.8.10 (2013-Apr-02) 133 | -------------------- 134 | 135 | *TODO* 136 | 137 | 138 | 0.8.9 (2013-Mar-25) 139 | ------------------- 140 | 141 | *TODO* 142 | 143 | 144 | 0.8.8 (2013-Mar-22) 145 | ------------------- 146 | 147 | *TODO* 148 | 149 | 150 | 0.8.7 (2013-Mar-22) 151 | ------------------- 152 | 153 | *ExtCore 0.8.7 was withdrawn due to a build issue.* 154 | 155 | 156 | 0.8.6 (2013-Mar-17) 157 | ------------------- 158 | 159 | *TODO* 160 | 161 | 162 | 0.8.5 (2013-Mar-13) 163 | ------------------- 164 | 165 | *TODO* 166 | 167 | 168 | 0.8.4 (2013-Mar-13) 169 | ------------------- 170 | 171 | *TODO* 172 | 173 | 174 | 0.8.3 (2013-Mar-11) 175 | ------------------- 176 | 177 | *TODO* 178 | 179 | 180 | 0.8.2 (2013-Mar-06) 181 | ------------------- 182 | 183 | *TODO* 184 | 185 | 186 | 0.8.1 (2013-Mar-06) 187 | ------------------- 188 | 189 | - Initial release. 190 | -------------------------------------------------------------------------------- /_docs/References.rst: -------------------------------------------------------------------------------- 1 | References 2 | ========== 3 | 4 | This document provides references to books and academic papers detailing algorithms implemented within ExtCore. 5 | 6 | `General`_ 7 | General algorithms. 8 | 9 | `String`_ 10 | String manipulation. 11 | 12 | `IntSet and IntMap`_ 13 | Maps with integer keys. 14 | 15 | 16 | General 17 | ------- 18 | 19 | *TODO* 20 | 21 | 22 | String 23 | ------ 24 | 25 | - "A Subsequence Algebra -- First Class Values for Substrings", Wilfred J. Hansen (1991) 26 | 27 | 28 | IntSet and IntMap 29 | ----------------- 30 | 31 | *NOTE : These references also apply to variants of `IntSet` and `IntMap`, such as `LongSet` and `TagMap`.* 32 | 33 | - "Fast Mergable Integer Maps", Gill, Okasaki (????) 34 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.0.{build} 2 | image: Visual Studio 2017 3 | build_script: 4 | - ps: >- 5 | ./install_dotnet.ps1 6 | - ps: >- 7 | ./install_dotnet.ps1 -Version 1.1.5 8 | - cmd: >- 9 | dotnet --version 10 | - cmd: >- 11 | dotnet build ExtCore.sln 12 | - cmd: >- 13 | dotnet test ExtCore.Tests\ExtCore.Tests.fsproj 14 | - cmd: >- 15 | dotnet pack 16 | test: off 17 | 18 | -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /proto-compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Paths to tools and sources 4 | unamestr=$(uname) 5 | if [ "$unamestr" = 'Linux' ]; then 6 | fsharp_dir=/home/jack/SourceCode/fsharp 7 | mono_lib_dir=/usr/local/lib/mono 8 | elif [ "$unamestr" = 'FreeBSD' ]; then 9 | fsharp_dir=/usr/home/jack/SourceCode/fsharp 10 | mono_lib_dir=/usr/local/lib/mono 11 | elif [ "$unamestr" = 'Darwin' ]; then 12 | fsharp_dir=/Users/jack/Code/fsharp 13 | mono_lib_dir=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono 14 | else 15 | echo "Unknown platform: $unamestr" 1>&2 16 | exit 1 17 | fi 18 | 19 | # Create build directory structure. 20 | mkdir build 21 | pushd build 22 | mkdir net40-Client 23 | mkdir net45 24 | mkdir profile47 25 | mkdir profile7 26 | mkdir profile78 27 | mkdir profile259 28 | popd 29 | 30 | # 31 | # Compile builds using the F# proto-compiler. 32 | # 33 | 34 | # Create the file list. 35 | extcore_files="ExtCore/Pervasive.fs ExtCore/Substring.fs ExtCore/String.fs ExtCore/Control.Agents.fs ExtCore/Control.fs ExtCore/Control.Observable.fs ExtCore/Control.Indexed.fs ExtCore/Control.Cps.fs ExtCore/Control.Tasks.fs ExtCore/Collections.fs ExtCore/Collections.Seq.fs ExtCore/Collections.ListZipper.fs ExtCore/Collections.List.fs ExtCore/Collections.Vector.fs ExtCore/Collections.VectorView.fs ExtCore/Collections.ResizeArray.fs ExtCore/Collections.Array.fs ExtCore/Collections.TaggedArray.fs ExtCore/Collections.ArrayView.fs ExtCore/Collections.Set.fs ExtCore/Collections.Map.fs ExtCore/Collections.Dict.fs ExtCore/Collections.Bimap.fs ExtCore/Collections.IntSet.fs ExtCore/Collections.IntMap.fs ExtCore/Collections.IntBimap.fs ExtCore/Collections.LongSet.fs ExtCore/Collections.LongMap.fs ExtCore/Collections.LongBimap.fs ExtCore/Collections.HashSet.fs ExtCore/Collections.HashMap.fs ExtCore/Collections.Multiset.fs ExtCore/Collections.Multimap.fs ExtCore/Collections.LazyList.fs ExtCore/Collections.Queue.fs ExtCore/Collections.PriorityQueue.fs ExtCore/Collections.AsyncSeq.fs ExtCore/ControlCollections.State.fs ExtCore/ControlCollections.Reader.fs ExtCore/ControlCollections.ReaderState.fs ExtCore/ControlCollections.Maybe.fs ExtCore/ControlCollections.ReaderMaybe.fs ExtCore/ControlCollections.Choice.fs ExtCore/ControlCollections.ReaderChoice.fs ExtCore/ControlCollections.ProtectedState.fs ExtCore/ControlCollections.ReaderProtectedState.fs ExtCore/ControlCollections.StatefulChoice.fs ExtCore/ControlCollections.Async.fs ExtCore/ControlCollections.AsyncState.fs ExtCore/ControlCollections.AsyncMaybe.fs ExtCore/ControlCollections.AsyncChoice.fs ExtCore/ControlCollections.AsyncProtectedState.fs ExtCore/ControlCollections.Cont.fs ExtCore/ControlCollections.StateCont.fs ExtCore/Caching.LruCache.fs ExtCore/NativeInterop.fs ExtCore/IO.fs ExtCore/Net.fs ExtCore/Args.fs ExtCore/ExtraPervasives.fs ExtCore/AssemblyInfo.fs" 36 | 37 | # net40-Client 38 | framework_lib_dir=4.0-api 39 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/net40-Client/ExtCore.dll --doc:./build/net40-Client/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll -r:$mono_lib_dir/$framework_lib_dir/System.Numerics.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_40 --define:FX_ATLEAST_FSHARP_3_0 --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 40 | 41 | # net45 42 | framework_lib_dir=4.5 43 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/net45/ExtCore.dll --doc:./build/net45/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll -r:$mono_lib_dir/$framework_lib_dir/System.Numerics.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_40 --define:FX_ATLEAST_45 --define:FX_ATLEAST_FSHARP_3_0 --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 44 | 45 | # profile7 (portable-net45+win8) (netstandard1.1) 46 | framework_lib_dir=xbuild-frameworks/.NETPortable/v4.5/Profile/Profile7 47 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/profile7/ExtCore.dll --doc:./build/profile7/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll -r:$mono_lib_dir/$framework_lib_dir/System.Numerics.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_FSHARP_3_0 --define:FX_NO_SYSTEM_CONSOLE --define:FX_ATLEAST_PORTABLE --define:FX_SIMPLE_DIAGNOSTICS --define:FX_NO_TPL_PARALLEL --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 48 | 49 | # profile47 (portable-net45+sl5+win8) 50 | framework_lib_dir=xbuild-frameworks/.NETPortable/v4.0/Profile/Profile47 51 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/profile47/ExtCore.dll --doc:./build/profile47/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll -r:$mono_lib_dir/$framework_lib_dir/System.Numerics.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_FSHARP_3_0 --define:FX_NO_SYSTEM_CONSOLE --define:FX_ATLEAST_PORTABLE --define:FX_SIMPLE_DIAGNOSTICS --define:FX_NO_TPL_PARALLEL --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 52 | 53 | # profile78 (portable-net45+win8+wp8) (netstandard1.0) 54 | framework_lib_dir=xbuild-frameworks/.NETPortable/v4.5/Profile/Profile78 55 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/profile78/ExtCore.dll --doc:./build/profile78/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_FSHARP_3_0 --define:FX_NO_SYSTEM_CONSOLE --define:FX_ATLEAST_PORTABLE --define:FX_SIMPLE_DIAGNOSTICS --define:FX_NO_TPL_PARALLEL --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 56 | 57 | # profile259 (portable-net45+win8+wpa81+wp8) (netstandard1.0) 58 | framework_lib_dir=xbuild-frameworks/.NETPortable/v4.5/Profile/Profile259 59 | mono $fsharp_dir/lib/proto/fsc-proto.exe -o:./build/profile259/ExtCore.dll --doc:./build/profile259/ExtCore.xml -r:$mono_lib_dir/$framework_lib_dir/System.dll -r:$mono_lib_dir/$framework_lib_dir/System.Core.dll --define:TRACE --define:PROTO_COMPILER --define:FX_ATLEAST_FSHARP_3_0 --define:FX_NO_SYSTEM_CONSOLE --define:FX_ATLEAST_PORTABLE --define:FX_SIMPLE_DIAGNOSTICS --define:FX_NO_TPL_PARALLEL --debug:pdbonly --optimize+ --fullpaths --nowarn:42,75,1204 --platform:anycpu --target:library --extraoptimizationloops:1 $extcore_files 60 | 61 | # TODO - Implement builds for netcore/netstandard profiles 62 | --------------------------------------------------------------------------------