Add purescript/slice
This commit is contained in:
parent
7c0fbb5f4a
commit
df8492f6ba
|
@ -14,6 +14,7 @@
|
||||||
| [maps](./maps) | Attempt at implementing maps with membership proofs |
|
| [maps](./maps) | Attempt at implementing maps with membership proofs |
|
||||||
| [proofs](./proofs) | Attempt at expressing mathematical proofs using Purescript's effect system |
|
| [proofs](./proofs) | Attempt at expressing mathematical proofs using Purescript's effect system |
|
||||||
| [purpleflow](./purpleflow) | Unfinished dependently-typed programming language |
|
| [purpleflow](./purpleflow) | Unfinished dependently-typed programming language |
|
||||||
|
| [slice](./slice) | Basic benchmarks and a `Slice` type |
|
||||||
| [sprint](./sprint) | Failled effect-system based on typelevel lists |
|
| [sprint](./sprint) | Failled effect-system based on typelevel lists |
|
||||||
| [streams](./streams) | Playing with `purescript-pipes` |
|
| [streams](./streams) | Playing with `purescript-pipes` |
|
||||||
| [typelevel](./typelevel) | Typelevel naturals, vectors, sum-types, orderings and lambda-calculus evaluation and a value-level bounded-type GADT |
|
| [typelevel](./typelevel) | Typelevel naturals, vectors, sum-types, orderings and lambda-calculus evaluation and a value-level bounded-type GADT |
|
||||||
|
|
11
purescript/slice/.gitignore
vendored
Normal file
11
purescript/slice/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/bower_components/
|
||||||
|
/node_modules/
|
||||||
|
/.pulp-cache/
|
||||||
|
/output/
|
||||||
|
/generated-docs/
|
||||||
|
/.psc-package/
|
||||||
|
/.psc*
|
||||||
|
/.purs*
|
||||||
|
/.psa*
|
||||||
|
/.spago
|
||||||
|
/tmp
|
6
purescript/slice/package.json
Normal file
6
purescript/slice/package.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "purescript-experiments",
|
||||||
|
"dependencies": {
|
||||||
|
"benchmark": "^2.1.4"
|
||||||
|
}
|
||||||
|
}
|
18
purescript/slice/packages.dhall
Normal file
18
purescript/slice/packages.dhall
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
let upstream =
|
||||||
|
https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20210118/packages.dhall sha256:a59c5c93a68d5d066f3815a89f398bcf00e130a51cb185b2da29b20e2d8ae115
|
||||||
|
|
||||||
|
let additions =
|
||||||
|
{ zipperarray =
|
||||||
|
{ dependencies =
|
||||||
|
[ "arrays", "maybe", "prelude", "naturals", "strictlypositiveint" ]
|
||||||
|
, repo = "https://github.com/jamieyung/purescript-zipperarray/"
|
||||||
|
, version = "master"
|
||||||
|
}
|
||||||
|
, strictlypositiveint =
|
||||||
|
{ dependencies = [ "prelude" ]
|
||||||
|
, repo = "https://github.com/jamieyung/purescript-strictlypositiveint"
|
||||||
|
, version = "master"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in additions ⫽ upstream
|
21
purescript/slice/pnpm-lock.yaml
Normal file
21
purescript/slice/pnpm-lock.yaml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
dependencies:
|
||||||
|
benchmark: 2.1.4
|
||||||
|
lockfileVersion: 5.1
|
||||||
|
packages:
|
||||||
|
/benchmark/2.1.4:
|
||||||
|
dependencies:
|
||||||
|
lodash: 4.17.21
|
||||||
|
platform: 1.3.6
|
||||||
|
dev: false
|
||||||
|
resolution:
|
||||||
|
integrity: sha1-CfPeMckWQl1JjMLuVloOvzwqVik=
|
||||||
|
/lodash/4.17.21:
|
||||||
|
dev: false
|
||||||
|
resolution:
|
||||||
|
integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
/platform/1.3.6:
|
||||||
|
dev: false
|
||||||
|
resolution:
|
||||||
|
integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
|
||||||
|
specifiers:
|
||||||
|
benchmark: ^2.1.4
|
10
purescript/slice/spago.dhall
Normal file
10
purescript/slice/spago.dhall
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{-
|
||||||
|
Welcome to a Spago project!
|
||||||
|
You can edit this file as you like.
|
||||||
|
-}
|
||||||
|
{ name = "my-project"
|
||||||
|
, dependencies =
|
||||||
|
[ "benchotron", "console", "effect", "psci-support", "st", "zipperarray" ]
|
||||||
|
, packages = ./packages.dhall
|
||||||
|
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||||
|
}
|
23
purescript/slice/src/Benchmarks.js
Normal file
23
purescript/slice/src/Benchmarks.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
exports.arraySum = function (v) {
|
||||||
|
if (v.length) {
|
||||||
|
const [head, ...tail] = v;
|
||||||
|
return (head + exports.arraySum(tail)) | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.arrayFib = (function () {
|
||||||
|
var go = function (a) {
|
||||||
|
return function (b) {
|
||||||
|
return function (v) {
|
||||||
|
if (v === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
var c = (a + b) | 0;
|
||||||
|
return [c, ...go(c)(a)((v - 1) | 0)];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return go(1)(1);
|
||||||
|
})();
|
111
purescript/slice/src/Benchmarks.purs
Normal file
111
purescript/slice/src/Benchmarks.purs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
module Benchmarks where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Benchotron.Core (Benchmark, benchFn, benchFn', mkBenchmark)
|
||||||
|
import Control.Monad.ST.Internal as ST
|
||||||
|
import Control.Monad.ST.Internal as STRef
|
||||||
|
import Data.Array (foldMap, foldr, foldl, (..))
|
||||||
|
import Data.Array.NonEmpty as NonEmptyArray
|
||||||
|
import Data.Array.ST as STArray
|
||||||
|
import Data.List (List(..), (:))
|
||||||
|
import Data.List as List
|
||||||
|
import Data.Maybe (Maybe(..))
|
||||||
|
import Data.Monoid.Additive (Additive(..))
|
||||||
|
import Data.ZipperArray (ZipperArray)
|
||||||
|
import Data.ZipperArray as ZipperArray
|
||||||
|
import Slice (Slice)
|
||||||
|
import Slice as Slice
|
||||||
|
import Test.QuickCheck (arbitrary)
|
||||||
|
import Test.QuickCheck.Gen (vectorOf)
|
||||||
|
|
||||||
|
listSum :: List Int -> Int
|
||||||
|
listSum (head:tail) = head + listSum tail
|
||||||
|
listSum _ = 0
|
||||||
|
|
||||||
|
listSumTCO :: List Int -> Int
|
||||||
|
listSumTCO = go 0
|
||||||
|
where
|
||||||
|
go s Nil = s
|
||||||
|
go s (head:tail) = go (s + head) tail
|
||||||
|
|
||||||
|
zipperSum :: ZipperArray Int -> Int
|
||||||
|
zipperSum arr = ZipperArray.current arr + case ZipperArray.goNext arr of
|
||||||
|
Nothing -> 0
|
||||||
|
Just next -> zipperSum next
|
||||||
|
|
||||||
|
sliceSum :: Slice Int -> Int
|
||||||
|
sliceSum arr = case Slice.uncons arr of
|
||||||
|
Nothing -> 0
|
||||||
|
Just { head, tail } -> head + sliceSum tail
|
||||||
|
|
||||||
|
sliceSumTCO :: Slice Int -> Int
|
||||||
|
sliceSumTCO = go 0
|
||||||
|
where
|
||||||
|
go s arr = case Slice.uncons arr of
|
||||||
|
Nothing -> s
|
||||||
|
Just { head, tail } -> go (s + head) tail
|
||||||
|
|
||||||
|
listFib :: Int -> List Int
|
||||||
|
listFib = go 1 1
|
||||||
|
where
|
||||||
|
go a b 0 = Nil
|
||||||
|
go a b n = c:go c a (n - 1)
|
||||||
|
where
|
||||||
|
c = a + b
|
||||||
|
|
||||||
|
stArrayFib :: Int -> Array Int
|
||||||
|
stArrayFib to = STArray.run do
|
||||||
|
a <- STRef.new 1
|
||||||
|
b <- STRef.new 1
|
||||||
|
result <- STArray.empty
|
||||||
|
ST.for 1 to \_ -> do
|
||||||
|
a' <- STRef.read a
|
||||||
|
b' <- STRef.read b
|
||||||
|
let c = a' + b'
|
||||||
|
void
|
||||||
|
$ STArray.push c result
|
||||||
|
<* STRef.write a' b
|
||||||
|
<* STRef.write c a
|
||||||
|
pure result
|
||||||
|
|
||||||
|
foreign import arraySum :: Array Int -> Int
|
||||||
|
foreign import arrayFib :: Int -> Array Int
|
||||||
|
|
||||||
|
benchSum :: Benchmark
|
||||||
|
benchSum = mkBenchmark
|
||||||
|
{ slug: "sum"
|
||||||
|
, title: "Finding the sum of a sequence of integers"
|
||||||
|
, sizes: (1..10) <#> (_ * 1000)
|
||||||
|
, sizeInterpretation: "Number of elements in the array"
|
||||||
|
, inputsPerSize: 1
|
||||||
|
, gen: \n -> NonEmptyArray.cons' <$> arbitrary <*> vectorOf n arbitrary
|
||||||
|
, functions: [
|
||||||
|
-- benchFn' "array" arraySum NonEmptyArray.toArray
|
||||||
|
benchFn' "list" listSum List.fromFoldable
|
||||||
|
, benchFn' "list (tail call optimization" listSumTCO List.fromFoldable
|
||||||
|
, benchFn' "zipper" zipperSum ZipperArray.fromNonEmptyArray
|
||||||
|
, benchFn' "array slice" sliceSum (NonEmptyArray.toArray >>> Slice.fromArray)
|
||||||
|
, benchFn' "array slice (tail call optimization)" sliceSumTCO (NonEmptyArray.toArray >>> Slice.fromArray)
|
||||||
|
, benchFn' "array foldr" (foldr (+) 0) NonEmptyArray.toArray
|
||||||
|
, benchFn' "array foldl" (foldl (+) 0) NonEmptyArray.toArray
|
||||||
|
, benchFn' "array foldMap" (foldMap Additive) NonEmptyArray.toArray
|
||||||
|
, benchFn' "list foldr" (foldr (+) 0) List.fromFoldable
|
||||||
|
, benchFn' "list foldl" (foldl (+) 0) List.fromFoldable
|
||||||
|
, benchFn' "list foldMap" (foldMap Additive) List.fromFoldable
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
benchFib :: Benchmark
|
||||||
|
benchFib = mkBenchmark
|
||||||
|
{ slug: "fibonacci"
|
||||||
|
, title: "Generating the first n fibonacci numbers as a sequence"
|
||||||
|
, sizes: (1..10) <#> (_ * 100)
|
||||||
|
, sizeInterpretation: "Number of elements"
|
||||||
|
, inputsPerSize: 1
|
||||||
|
, gen: pure
|
||||||
|
, functions: [ benchFn "array" arrayFib
|
||||||
|
, benchFn "list" listFib
|
||||||
|
, benchFn "stArray" stArrayFib
|
||||||
|
]
|
||||||
|
}
|
20
purescript/slice/src/Main.purs
Normal file
20
purescript/slice/src/Main.purs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Benchmarks (benchSum)
|
||||||
|
import Benchotron.UI.Console (runSuite)
|
||||||
|
import Control.Monad.ST.Internal as ST
|
||||||
|
import Control.Monad.ST.Internal as STRef
|
||||||
|
import Effect (Effect)
|
||||||
|
|
||||||
|
factorial :: Int -> Int
|
||||||
|
factorial to = ST.run do
|
||||||
|
result <- STRef.new 1
|
||||||
|
ST.for 2 to \index -> do
|
||||||
|
current <- STRef.read result
|
||||||
|
STRef.write (current * index) result
|
||||||
|
STRef.read result
|
||||||
|
|
||||||
|
main :: Effect Unit
|
||||||
|
main = runSuite [benchSum]
|
32
purescript/slice/src/Slice.purs
Normal file
32
purescript/slice/src/Slice.purs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
module Slice where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.Array as Array
|
||||||
|
import Data.Maybe (Maybe(..))
|
||||||
|
import Partial.Unsafe (unsafePartial)
|
||||||
|
|
||||||
|
newtype Slice a
|
||||||
|
= Slice
|
||||||
|
{ array :: Array a
|
||||||
|
, at :: Int
|
||||||
|
, length :: Int }
|
||||||
|
|
||||||
|
uncons :: forall a. Slice a -> Maybe { head :: a, tail :: Slice a }
|
||||||
|
uncons (Slice { length, at, array })
|
||||||
|
= if length == 0
|
||||||
|
then Nothing
|
||||||
|
else Just
|
||||||
|
{ head: unsafePartial $ Array.unsafeIndex array at
|
||||||
|
, tail: Slice { length: length - 1, at: at + 1, array } }
|
||||||
|
|
||||||
|
uncons' :: forall a r. Slice a -> { nil :: r, cons :: a -> Slice a -> r } -> r
|
||||||
|
uncons' (Slice { length, at, array }) cases
|
||||||
|
= if length == 0
|
||||||
|
then cases.nil
|
||||||
|
else cases.cons
|
||||||
|
(unsafePartial $ Array.unsafeIndex array at)
|
||||||
|
(Slice { length: length - 1, at: at + 1, array })
|
||||||
|
|
||||||
|
fromArray :: forall a. Array a -> Slice a
|
||||||
|
fromArray array = Slice { array, at: 0, length: Array.length array }
|
11
purescript/slice/test/Main.purs
Normal file
11
purescript/slice/test/Main.purs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module Test.Main where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Class.Console (log)
|
||||||
|
|
||||||
|
main :: Effect Unit
|
||||||
|
main = do
|
||||||
|
log "🍝"
|
||||||
|
log "You should add some tests."
|
Loading…
Reference in a new issue