GithubHelp home page GithubHelp logo

base_v1's Introduction

Unison base libraries

This includes basic data types and functions for the Unison language. See CONTRIBUTING.md for how to contribute.

Installation

From the Unison Codebase Manager (ucm) prompt:

.> pull https://github.com/unisonweb/base:.releases._latest .base

This will install the libraries into your codebase, under a namespace called .base.

Usage

In Unison:

use .base

What's here?

You can explore this library using the Codebase Manager (ucm). After installation (see above), type cd .base, then use the ls, cd, and view commands to explore.

base_v1's People

Contributors

anovstrup avatar aryairani avatar galer1us avatar orvi avatar pchiusano avatar runarorama avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

base_v1's Issues

a few functions: inRange/max/min, xor, all/any/none, iterate/until

A few functions for base, written in passing as I was working on PRNG stuff.

Things to highlight

  • the function I'm proposing to call iterate has a different signature from the haskell function of the same name (and from Runar's function in his lib https://github.com/runarorama/unisonlibraries)
    • Haskell has (a -> a) -> a -> [a]
    • Runar has Nat -> (a ->{๐•–} a) -> a ->{๐•–} [a]
    • I have Nat -> '{e} a ->{e} [a]
  • I'm proposing to give my (a ->{e} Boolean) -> '{e} a ->{e} a the name until
  • the inRange functions are inclusive on the left but exclusive on the right

Code review

  The changes summarized below are available for you to review, using the following command:
  
    pull-request.load https://github.com/unisonweb/base https://github.com/atacratic/unisonweb-base
  
  Added definitions:
  
     Int.inRange                          : Int -> Int -> Int -> Boolean (+3 metadata)
     Int.inRange.doc                      : Doc (+2 metadata)
     Int.max                              : Int -> Int -> Int (+2 metadata)
     Int.min                              : Int -> Int -> Int (+2 metadata)
     List.all                             : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} Boolean (+2 metadata)
     List.any                             : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} Boolean (+2 metadata)
     List.none                            : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} Boolean (+2 metadata)
     Nat.inRange                          : Nat -> Nat -> Nat -> Boolean (+3 metadata)
     Nat.inRange.doc                      : Doc (+2 metadata)
     Nat.max                              : Nat -> Nat -> Nat (+2 metadata)
     Nat.min                              : Nat -> Nat -> Nat (+2 metadata)
     iterate                              : Nat -> '{e} a ->{e} [a] (+3 metadata)
     iterate.doc                          : Doc (+2 metadata)
     iterate.test                         : [Result] (+3 metadata)
     metadata.authors.atacratic           : Author
     metadata.authors.atacratic.guid      : GUID
     metadata.copyrightHolders.atacratic  : CopyrightHolder
     metadata.licenses.atacratic.mit_2020 : License
     until                                : (a ->{e} Boolean) -> '{e} a ->{e} a (+3 metadata)
     until.doc                            : Doc (+2 metadata)
     xor                                  : Boolean -> Boolean -> Boolean (+3 metadata)
     xor.doc                              : Doc (+2 metadata)
     xor.test                             : [Result] (+3 metadata)
  
     patch patch (added 1 updates)
     patch patches.dev (added 3 updates)
  
  Name changes:
  
    Original                                                       Changes
     releases._M1j.Abort                                        โ”   Abort (added)
     releases._M1k.Abort                                        โ”‚  
     releases._M1l.Abort                                        โ”‚  
     releases._latest.Abort                                     โ”‚  
     trunk.Abort                                                โ”˜  
    
     releases._M1j.Ask                                          โ”   Ask (added)
     releases._M1k.Ask                                          โ”‚  
     releases._M1l.Ask                                          โ”‚  
     releases._latest.Ask                                       โ”‚  
     trunk.Ask                                                  โ”˜  

...    

... and lots more name changes like that. Is this fishy?

Also not sure why it's flagging patch changes - the two patches don't contain anything related to my additions.

Add `Set.unions` and `Set.flatten` and necessary dependencies

This adds Set.unions and Set.flatten, along with their missing dependencies.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/runarorama/mybase:.prs._pr28

Added definitions:

 Int.decrement                 : Int -> Int (+3 metadata)
 Int.decrement.doc             : Doc (+2 metadata)
 Int.decrement.test            : [Result] (+3 metadata)
 List.foldr                    : (a ->{e} b ->{e} b)
                               -> b
                               -> [a]
                               ->{e} b (+3 metadata)
 List.foldr.doc                : Doc (+2 metadata)
 List.foldr.tests.homomorphism : [Result] (+3 metadata)
 Nat.decrement                 : Nat -> Nat (+3 metadata)
 Nat.decrement.doc             : Doc (+2 metadata)
 Nat.decrement.test            : [Result] (+3 metadata)
 Set.flatMap                   : (a ->{e} Set b)
                               -> Set a
                               ->{e} Set b (+3 metadata)
 Set.flatMap.doc               : Doc (+2 metadata)
 Set.flatMap.tests.associative : [Result] (+3 metadata)
 Set.flatMap.tests.unit        : [Result] (+3 metadata)
 Set.flatten                   : Set (Set b) -> Set b (+3 metadata)
 Set.flatten.doc               : Doc (+2 metadata)
 Set.flatten.tests.associative : [Result] (+3 metadata)
 Set.flatten.tests.unit        : [Result] (+3 metadata)
 Set.foldl                     : (b ->{e} a ->{e} b)
                               -> b
                               -> Set a
                               ->{e} b (+3 metadata)
 Set.foldl.doc                 : Doc (+2 metadata)
 Set.foldl.tests.homomorphism  : [Result] (+3 metadata)
 Set.foldr                     : (a ->{e} b ->{e} b)
                               -> b
                               -> Set a
                               ->{e} b (+3 metadata)
 Set.foldr.doc                 : Doc (+2 metadata)
 Set.foldr.tests.homomorphism  : [Result] (+3 metadata)
 Set.unions                    : [Set a] -> Set a (+3 metadata)
 Set.unions.doc                : Doc (+2 metadata)
 Set.unions.test               : [Result] (+3 metadata)

Recursive generators crash with a bug

Using the following test

test.optional : '{Gen} a -> '{Gen} Optional a
test.optional gen =
  'let
    b = !test.boolean
    if b then None else Some !gen

test.boolean =
  '(Gen.sample (Weighted.fromList [false, true]))

test> Trie.union.tests.keys = runs 2 'let
  t1 = !(Trie.gen nat nat)
  t2 = !(Trie.gen nat nat)
  t2vs = Trie.values t2
  uvs = Trie.values (Trie.union t1 t2)
  expect (List.all (v -> uvs `List.contains` v) t2vs)

Trie.gen : '{Gen} k ->{} '{Gen} v ->{} '{Gen} (Trie k v)
Trie.gen k v = 'let
  h = !(optional v)
  g = Trie.gen k v
  t = !(mapOf k g)
  Trie h t

Results in this crash:

 ๐Ÿ’”๐Ÿ’ฅ

  I stopped evaluation after encountering an unhandled request:

    Gen.sample
      let
        use Nat + drop
        use Weighted Fail
        โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o3
          m n =
          match (m, n) with
            (Fail, n)                 -> n
            (Yield x m, n)            ->
              Yield
                x
                (โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                  m n)
            (Weight w m, Fail)        -> Weight w m
            (Weight w m, Yield x n)   ->
              Yield
                x
                (โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                  (Weight w m) n)
            (Weight w m, Weight w' n) ->
              if w < w' then
                Weight
                  w
                  '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                    !m (Weight (drop w' w) n))
              else
                if w == w' then
                  Weight
                    w
                    '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                      !m !n)
                else
                  Weight
                    w
                    '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                      (Weight (drop w w') m) !n)
        go8 =
          (go
          โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
          โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
          โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
          n ->
            โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
              (โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
                n)
              (โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
                1 '(go (n + 1))))
            go
            โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
            (w ws -> Weight w ws)
            (a -> Yield a Fail)
        Yield
          0
          (Weight
            1
            ((go n -> '(go (n + 1)))
              ((go
              โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
              โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
              โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
              n ->
                โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                  (โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
                    n)
                  (โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
                    1 '(go (n + 1))))
                ((go
                โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
                โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
                n ->
                  โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                    (โ„#tbb39c2i34bkepv8r43il0auhnbao55ftft9d18c5fq31f0gk6utf7v6ghnt76h8r8l1eesrsgsac4b0klqpoktofq6m7p2esck5id0
                      n)
                    (โ„#e2dsohsu6ra6kgimsi1i32lln9s7e4vc4ua66afag9k8o9vm0omv28ilolsvlju5o5ioq0bm9vfu2o92akk2ddkrekmpk1vudl3vak8
                      1 '(go (n + 1))))
                  go
                  โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                  (w ws -> Weight w ws)
                  (a -> Yield a Fail))
                (m n ->
                  (match (m, n) with
                    (Fail, n)                 -> n
                    (Yield x m, n)            ->
                      Yield
                        x
                        (โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                          m n)
                    (Weight w m, Fail)        -> Weight w m
                    (Weight w m, Yield x n)   ->
                      Yield
                        x
                        (โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                          (Weight w m) n)
                    (Weight w m, Weight w' n) ->
                      if w < w' then
                        Weight
                          w
                          '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                            !m (Weight (drop w' w) n))
                      else
                        if w == w' then
                          Weight
                            w
                            '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                              !m !n)
                        else
                          Weight
                            w
                            '(โ„#b3tl0p6em4l1l9flulpe7mksfe4egpbp84rfh4iacfriqp01k3p617tr4h32s4i1s9pkd6jgp02vlhtatb6rrgeha2b6j5rbptk3r7o
                              (Weight (drop w w') m) !n)))
                (w ws -> Weight w ws)
                (a -> Yield a Fail))
              0))

  This happens when using a handler that doesn't handle all possible requests.

  I'm sorry this message doesn't have more detail about the location of the
  failure. My makers plan to fix this in a future release. ๐Ÿ˜ข

Property test with 6+ uses of a generator locks up

The following locks up indefinitely during evaluation, spinning the CPU (but not eating memory).

eg =
  go _ =
    t =
      !int
        * +25
        + !int
        * +4
        + !int
        * +12
        + !int
        * +30
        + !int
        * +24
        + !int
--        * +60
--        + !int
--        * +60
--        + !int
    expect true
  .base.test.runs 1 go

Six uses of !int seems to be the minimal number to generate the lockup. With five uses evaluation takes about 7 seconds for me.

Related to #45 maybe?

[edit] ah, not 'indefinitely': it's about a minute for 6 uses, and grows as you add more

add gen.optional and gen.either tests

Based on the approach suggested by @runarorama here. The 10 argument being passed to sample is arbitrary; I just wanted to make sure that if you sample more items than are in the domain things still work. We could potentially add a version of sample that is unbounded, but I wasn't sure if that added much value.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load [email protected]:unisonweb/base:.trunk [email protected]:ceedubs/unison-dev:.prs.base._genTests

Added definitions:

 test.gen.either.test   : [Result] (+3 metadata)
 test.gen.optional.test : [Result] (+3 metadata)

Add nonempty lists

This adds List.Nonempty, the type of nonempty lists, and a number of supporting operations.

Note

Removed gen.nats1 in favor of the atLeastOne combinator that generates a Nonempty of the given type.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/runarorama/mybase:._topic.nel

Added definitions:

1.  type List.Nonempty a (+5 metadata)
2.  List.Nonempty.Nonempty                      : a
                                                -> [a]
                                                -> Nonempty a
3.  โ”Œ List.Nonempty.++                          : Nonempty a
                                                -> Nonempty a
                                                -> Nonempty a (+3 metadata)
4.  โ”” List.Nonempty.append                      : Nonempty a
                                                -> Nonempty a
                                                -> Nonempty a (+3 metadata)
5.  List.Nonempty.+|                            : a
                                                -> [a]
                                                -> Nonempty a (+4 metadata)
6.  List.Nonempty.append.doc                    : Doc (+2 metadata)
7.  List.Nonempty.append.tests.associative      : [Test.Result] (+3 metadata)
8.  List.Nonempty.append.tests.homomorphism     : [Test.Result] (+3 metadata)
9.  List.Nonempty.cons                          : a
                                                -> Nonempty a
                                                -> Nonempty a (+3 metadata)
10. List.Nonempty.cons.doc                      : Doc (+2 metadata)
11. List.Nonempty.doc                           : Doc (+2 metadata)
12. List.Nonempty.examples.construction.ex1     : Nonempty Nat (+2 metadata)
13. List.Nonempty.examples.construction.ex2     : Optional
                                                  (Nonempty Nat) (+2 metadata)
14. List.Nonempty.flatMap                       : (a ->{e} Nonempty b)
                                                -> Nonempty a
                                                ->{e} Nonempty b (+3 metadata)
15. List.Nonempty.flatMap.doc                   : Doc (+2 metadata)
16. List.Nonempty.flatMap.tests.flatMapIdIsjoin : [Test.Result] (+3 metadata)
17. List.Nonempty.foldMap                       : (b ->{e} b ->{e} b)
                                                -> (a ->{e} b)
                                                -> Nonempty a
                                                ->{e} b (+3 metadata)
18. List.Nonempty.foldMap.doc                   : Doc (+2 metadata)
19. List.Nonempty.foldMap.examples.ex1          : Text (+2 metadata)
20. List.Nonempty.foldMap.test                  : [Test.Result] (+3 metadata)
21. List.Nonempty.foldl                         : (a ->{e} a ->{e} a)
                                                -> Nonempty a
                                                ->{e} a (+3 metadata)
22. List.Nonempty.foldl.doc                     : Doc (+2 metadata)
23. List.Nonempty.foldl.test                    : [Test.Result] (+3 metadata)
24. List.Nonempty.foldr                         : (a ->{e} a ->{e} a)
                                                -> Nonempty a
                                                ->{e} a (+3 metadata)
25. List.Nonempty.foldr.doc                     : Doc (+2 metadata)
26. List.Nonempty.foldr.test                    : [Test.Result] (+3 metadata)
27. List.Nonempty.head                          : Nonempty a
                                                -> a (+3 metadata)
28. List.Nonempty.head.doc                      : Doc (+2 metadata)
29. List.Nonempty.head.test                     : [Test.Result] (+3 metadata)
30. List.Nonempty.init                          : Nonempty a
                                                -> [a] (+3 metadata)
31. List.Nonempty.init.doc                      : Doc (+2 metadata)
32. List.Nonempty.init.test                     : [Test.Result] (+3 metadata)
33. List.Nonempty.join                          : Nonempty
                                                  (Nonempty a)
                                                -> Nonempty a (+3 metadata)
34. List.Nonempty.join.doc                      : Doc (+2 metadata)
35. List.Nonempty.join.examples.ex1             : Nonempty Nat (+2 metadata)
36. List.Nonempty.join.tests.associative        : [Test.Result] (+3 metadata)
37. List.Nonempty.join.tests.unit               : [Test.Result] (+3 metadata)
38. List.Nonempty.last                          : Nonempty a
                                                -> a (+3 metadata)
39. List.Nonempty.last.doc                      : Doc (+2 metadata)
40. List.Nonempty.last.test                     : [Test.Result] (+3 metadata)
41. List.Nonempty.map                           : (a ->{e} b)
                                                -> Nonempty a
                                                ->{e} Nonempty b (+3 metadata)
42. List.Nonempty.map.doc                       : Doc (+2 metadata)
43. List.Nonempty.map.tests.functor             : [Test.Result] (+3 metadata)
44. List.Nonempty.singleton                     : a
                                                -> Nonempty a (+3 metadata)
45. List.Nonempty.singleton.doc                 : Doc (+2 metadata)
46. List.Nonempty.singleton.test                : [Test.Result] (+3 metadata)
47. List.Nonempty.size                          : Nonempty a
                                                -> Nat (+3 metadata)
48. List.Nonempty.size.doc                      : Doc (+2 metadata)
49. List.Nonempty.size.test                     : [Test.Result] (+3 metadata)
50. List.Nonempty.snoc                          : Nonempty a
                                                -> a
                                                -> Nonempty a (+3 metadata)
51. List.Nonempty.snoc.doc                      : Doc (+2 metadata)
52. List.Nonempty.tail                          : Nonempty a
                                                -> [a] (+3 metadata)
53. List.Nonempty.tail.doc                      : Doc (+2 metadata)
54. List.Nonempty.tail.test                     : [Test.Result] (+3 metadata)
55. List.Nonempty.toList                        : Nonempty a
                                                -> [a] (+3 metadata)
56. List.Nonempty.toList.doc                    : Doc (+2 metadata)
57. List.Nonempty.|+                            : [a]
                                                -> a
                                                -> Nonempty a (+2 metadata)
58. List.nonempty                               : [a]
                                                -> Optional
                                                  (Nonempty a) (+3 metadata)
59. List.nonempty.doc                           : Doc (+2 metadata)
60. test.gen.atLeastOne                         : '{Gen} a
                                                -> '{Gen} Nonempty a (+3 metadata)
61. test.gen.atLeastOne.doc                     : Doc (+2 metadata)

Removed definitions:

62. test.gen.nats1     : '{Gen} [Nat]
63. test.gen.nats1.doc : Doc

Add test.gen.Gen.either

Disclaimer: I have no idea what I'm doing.

Before submitting a pull request, please doublecheck that you have included

[x] a clear PR description (don't bother to include issues numbers).
[x] Docs linked for types and terms as needed
[ ] Author and License metadata linked
I've added author metadata, but I'm not sure that I did it right. Afterwards I saw that the contributing guidelines said that someone would do this for me when I opened my PR, so I held off on adding licensing info.
[x] Tests, where appropriate

This PR adds test.gen.Gen.either:

> view test.gen.Gen.either

  test.gen.Gen.either : '{Gen} a -> '{Gen} b -> '{Gen} Either a b
  test.gen.Gen.either a b = pick ['(Left !a), '(Right !b)]
> docs test.gen.Gen.either

  
  Given the ability to generate values of type `a` and the ability to generate values of type `b`, generate
  `Either a b` values, alternating between `Left a` and `Right b`.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load [email protected]:unisonweb/base:.trunk [email protected]:ceedubs/unison-base:.prs._genEither

Added definitions:

 metadata.authors.ceedubs          : Author
 metadata.authors.ceedubs.guid     : GUID
 metadata.copyrightHolders.ceedubs : CopyrightHolder
 test.gen.Gen.either               : '{Gen} a -> '{Gen} b -> '{Gen} Either a b (+2 metadata)
 test.gen.Gen.either.doc           : Doc
 test.gen.Gen.either.test          : [Result] (+2 metadata)

unable to evaluate a sample expression

NOTE: I'm not really sure whether this is an issue with ucm or with corrupt data in the base repo. It may be both.

I'm currently using stack to build ucm from commit 9dc6a42619072e68d856c1f2605045a3cc14b890 since I'm not able to pull base with the latest release (M1l). It's possible that there's something wrong with my environment, but I don't think that's the issue since expressions like > 1 + 2 evaluate fine.

If I put > 1 + 2 in scratch.u, ucm does what I would expect:

.>                                    
                                                                    
  โœ…                                                                                                                                     
     
  scratch.u changed.                                                                                                                    
   
  Now evaluating any watch expressions (lines starting with `>`)... Ctrl+C cancels.
                                                                    
                                                                    
    1 | > 1 + 2
          โงฉ
          3

When I add > sample 5 nat, ucm crashes with the following:

unison: no type declaration for #bpcuh
CallStack (from HasCallStack):
  error, called at src/Unison/Runtime/Rt1.hs:236:20 in unison-parser-typechecker-0.1-1n4fxMa6V58C0oQoOr6uen:Unison.Runtime.Rt1

Strangely, if I add the following:

test.gen.optional : '{Gen} a -> '{Gen} (Optional a)
test.gen.optional a = Gen.append ('(Gen.sample (yield None))) '(Some !a)

then when I save the file I see a new .> line that suggests that ucm has detected the change to the file, but it's silent and doesn't say that there's a new term that's okay to add. Similarly if I add an expression evaluation below this, I don't see any output for it.

Documents and unit tests existing Search functions

Overview

This PR adds documentation sections for the Search functions. The documentation added highlights that binary search is used under the hood, and suggests using the search functions only on sorted lists. Cornercases added to specifically showcase that unless the input is sorted, the functions (as expected) do not find elements that are otherwise in the list.

  • Unit tests โœ”๏ธ
  • Docs linked against functions โœ”๏ธ
  • Author/Licence โž– as these are not mine.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base:.prs.searchDocumentation

Updates:

 Search.anyIndexOf : a -> [a] -> Optional Nat
 +  anyIndexOf.doc : Doc

 Search.exact : (Nat ->{๐•–} Int) -> Nat -> Nat ->{๐•–} Optional Nat
 +  exact.doc : Doc

 Search.lub : (Nat ->{๐•–} Int) -> Nat -> Nat ->{๐•–} Nat
 +  lub.doc : Doc

 Search.lubIndexOf : a -> [a] -> Nat
 +  lubIndexOf.doc : Doc

 patch patch (added 1 updates)

Added definitions:

 patch patch (added 1 updates)

Added definitions:

 Search.anyIndexOf.doc                        : Doc
 Search.anyIndexOf.evaluated.empty            : Optional Nat
 Search.anyIndexOf.evaluated.lower            : Optional Nat
 Search.anyIndexOf.evaluated.notSorted        : Optional Nat
 Search.anyIndexOf.evaluated.sorted           : Optional Nat
 Search.anyIndexOf.evaluated.upper            : Optional Nat
 โ”Œ Search.anyIndexOf.examples.input.lower     : [Nat]
 โ”” Search.anyIndexOf.examples.input.notSorted : [Nat]
 Search.anyIndexOf.examples.input.upper       : [Nat]
 Search.anyIndexOf.tests.empty                : [Result] (+1 metadata)
 Search.anyIndexOf.tests.lower                : [Result] (+1 metadata)
 Search.anyIndexOf.tests.notSorted            : [Result] (+1 metadata)
 Search.anyIndexOf.tests.sorted               : [Result] (+1 metadata)
 Search.anyIndexOf.tests.upper                : [Result] (+1 metadata)
 Search.exact.doc                             : Doc
 Search.lub.doc                               : Doc
 Search.lubIndexOf'.doc                       : Doc
 Search.lubIndexOf.doc                        : Doc
 Search.lubIndexOf.evaluated.empty            : Nat
 Search.lubIndexOf.evaluated.notSorted        : Nat
 Search.lubIndexOf.evaluated.sorted           : Nat
 Search.lubIndexOf.tests.empty                : [Result] (+1 metadata)
 Search.lubIndexOf.tests.notSorted            : [Result] (+1 metadata)
 Search.lubIndexOf.tests.sorted               : [Result] (+1 metadata)

 patch Search.patch (added 7 updates)

Name changes:

Original                     Changes
 List.last.examples.elems     Search.anyIndexOf.examples.input.sorted (added)

Add simple utility functions

This Unison PR adds the following tiny utility functions, with corresponding documentation:

ignore : a -> ()
ignore _ = ()

void : (a ->{e} b) -> a ->{e} ()
void = (.) ignore

repeat : Nat -> '{e} a ->{e} ()
repeat n op =
  if n == 0 then () else
    !op
    repeat (n `drop` 1) op

forever : '{e} a ->{e} b
forever op = !op; forever op

force : '{e} a ->{e} a
force op = !op

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base https://github.com/anovstrup/unisonweb-base

Added definitions:

 force       : '{e} a ->{e} a (+1 metadata)
 force.doc   : Doc
 forever     : '{e} a ->{e} b (+1 metadata)
 forever.doc : Doc
 ignore      : a -> () (+1 metadata)
 ignore.doc  : Doc
 repeat      : Nat -> '{e} a ->{e} () (+1 metadata)
 repeat.doc  : Doc
 void        : (a ->{e} b) -> a ->{e} () (+1 metadata)
 void.doc    : Doc

Add Int.range

This issue aims to add the Int.range function to the base library.

  • Uses the same mechanism as Nat.range
  • Documented under range.doc and linked.
  • Author and License metadata linked ๐Ÿคทโ€โ™‚๏ธ
    *Unit tested with positive and negative scenarios.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.Int https://github.com/pete-ts/base:.base.Int

Added definitions:

 range                              : Int -> Int -> [Int] (+1 metadata)
 range.doc                          : Doc
 range.examples.invalid.descFromNeg : [Int]
 range.examples.invalid.descFromPos : [Int]
 range.examples.valid.ascFromNeg    : [Int]
 range.examples.valid.ascFromNeg2   : [Int]
 range.examples.valid.ascFromPos    : [Int]
 range.tests.invalid.descFromNeg    : [Result] (+1 metadata)
 range.tests.invalid.descFromPos    : [Result] (+1 metadata)
 range.tests.valid.ascFromNeg       : [Result] (+1 metadata)
 range.tests.valid.ascFromNeg2      : [Result] (+1 metadata)
 range.tests.valid.ascFromPos       : [Result] (+1 metadata)

 patch patch (added 1 updates)

Add common combinators on functions.

Adds a number of higher-order combinators on functions:

  • curry/uncurry
  • flip
  • fix
  • on

Includes example use cases in docs.

Code review

The changes summarized below are available for you to review, using the following
command:

pull-request.load https://github.com/unisonweb/base:.trunk.Function https://github.com/runarorama/mybase:.curry.Function

Added definitions:

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk.Function https://github.com/runarorama/mybase:.curry.Function

Added definitions:

 curry                                    : ((a, b) ->{e} c) -> a -> b ->{e} c (+3 metadata)
 curry.doc                                : Doc (+2 metadata)
 fix                                      : ('{e} a ->{e} a) ->{e} a (+3 metadata)
 fix.doc                                  : Doc (+2 metadata)
 fix.examples.factorial.explicitRecursion : Nat (+2 metadata)
 fix.examples.factorial.fixpoint          : Nat (+2 metadata)
 flip                                     : (a ->{e} b ->{e} c) -> b -> a ->{e} c (+3 metadata)
 flip.doc                                 : Doc (+2 metadata)
 on                                       : (b ->{e} b ->{e} c)
                                          -> (a ->{e} b)
                                          -> a
                                          -> a
                                          ->{e} c (+3 metadata)
 on.doc                                   : Doc (+2 metadata)
 on.examples.equalOn                      : Boolean (+2 metadata)
 uncurry                                  : (a ->{e} b ->{e} c) -> (a, b) ->{e} c (+3 metadata)
 uncurry.doc                              : Doc (+2 metadata)

Add `List.concat`, `List.concatMap` and `List.filterMap`

Hi! This is a small PR to see if I got everything right. Here are some simple List functions that are missing.


The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/emiflake/unison-emi.git:.prs.base._list_functions

Added definitions:

 List.concat                                    : [[a]] -> [a] (+3 metadata)
 List.concat.doc                                : Doc (+2 metadata)
 List.concat.tests.ex1                          : [Result] (+3 metadata)
 List.concatMap                                 : (a ->{๐•–} [b]) -> [a] ->{๐•–} [b] (+3 metadata)
 List.concatMap.doc                             : Doc (+2 metadata)
 List.concatMap.tests.concatMapIdentityIsConcat : [Result] (+3 metadata)
 List.concatMap.tests.ex1                       : [Result] (+3 metadata)
 List.concatMap.tests.ex2                       : [Result] (+3 metadata)
 List.filterMap                                 : (a ->{๐•–} Optional b)
                                                -> [a]
                                                ->{๐•–} [b] (+3 metadata)
 List.filterMap.doc                             : Doc (+2 metadata)
 List.filterMap.tests.ex1                       : [Result] (+3 metadata)
 metadata.authors.emiflake                      : Author
 metadata.authors.emiflake.guid                 : GUID
 metadata.copyrightHolders.emiflake             : CopyrightHolder
 metadata.licenses.emiflake_mit_2020            : License (+1 metadata)

Optional helpers + Search {elem, notElem, indexOf}

Overview

This PR adds:

  • Optional.isSome
  • Optional.isNone
  • Search.indexOf (guaranteed left most occurrence of a value)
  • Search.elem
  • Search.notElem

All functions added should have doc, author, license linked, as well as unit tests.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base:.prs.elemNotElemIndexOf

Added definitions:

 Optional.isNone                : Optional a -> Boolean (+3 metadata)
 Optional.isNone.doc            : Doc
 Optional.isSome                : Optional a -> Boolean (+3 metadata)
 Optional.isSome.doc            : Doc
 Search.elem                    : a -> [a] -> Boolean (+3 metadata)
 Search.elem.doc                : Doc
 Search.elem.tests.negative1    : [Result] (+1 metadata)
 Search.elem.tests.negative2    : [Result] (+1 metadata)
 Search.elem.tests.negative3    : [Result] (+1 metadata)
 Search.elem.tests.positive1    : [Result] (+1 metadata)
 Search.elem.tests.positive2    : [Result] (+1 metadata)
 Search.elem.tests.positive3    : [Result] (+1 metadata)
 Search.indexOf                 : a -> [a] -> Optional Nat (+3 metadata)
 Search.indexOf.doc             : Doc
 Search.indexOf.tests.negative1 : [Result] (+1 metadata)
 Search.indexOf.tests.negative2 : [Result] (+1 metadata)
 Search.indexOf.tests.negative3 : [Result] (+1 metadata)
 Search.indexOf.tests.positive1 : [Result] (+1 metadata)
 Search.indexOf.tests.positive2 : [Result] (+1 metadata)
 Search.indexOf.tests.positive3 : [Result] (+1 metadata)
 Search.notElem                 : a -> [a] -> Boolean (+3 metadata)
 Search.notElem.doc             : Doc

 patch Search.patch (added 7 updates)

[initial review] Pseudo-random number generator (Mersenne twister), plus Nat32

This PR gives people access to pseudo-random numbers. Plus it includes a couple of other things I needed along the way, to achieve that. I'm after an initial review now, even though I still have a bit more work to do anyway before it can be merged, which I will get on with in parallel.

[edited 28-Apr; still not complete; would still appreciate an initial review]

What's included:

  • a bunch of stuff under random.mersenne
  • Nat32 and a bunch of associated operators, for 32-bit arithmetic
  • a few bits and pieces:
    • boolean xor
    • 'iterate', similar to the existing 'repeat'.
    • until : (a ->{e} Boolean) -> '{e} a ->{e} a
    • all, any, none : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} Boolean
    • Nat.max, Nat.min, Nat.inRange; and similar for Int

Rationale for the Mersenne twister PRNG

The temptingly-simply one-liner linear congruential generators that sometimes get used for generating pseudo-random numbers are not sound for statistical use.

The Mersenne twister algorithm is sound for this use, and indeed is the most common choice in software libraries, see https://en.wikipedia.org/wiki/Mersenne_Twister#Adoption_in_software_systems

It's not sound for cryptographic use, as is prominently noted in the docs.

Since this is a pseudo-random number generator, it is suitable for use in pure programs. Exposing other sources of true randomness through IO (with the help of the OS and/or RDRAND instruction) is out of scope for now.

Things to highlight to reviewers

  • I've wrapped Nat in a Nat32 type, so I can keep the top 32 bits zeroed out as I do math on the bottom 32 bits, without having to think too hard. The Nat32 stuff would all look very different in a language with newtypes and typeclasses. I've taken some inspiration from haskell's Data.bits anyway, just in terms of naming.
  • My definition type Nat32 = Nat32 Nat does not specify unique at the moment. Should it?
  • Is the name I've used for mkNat32 : Nat -> Optional Nat32 OK? Is there a convention here?
  • The name I've chosen for iterate (note Haskell has a different function with the same name), and note also the similarity to repeat.
  • Is trunk.random.mersenne.doc named OK?
  • Nat.inRange and Int.inRange are inclusive on the left but exclusive on the right.
  • The API uses the existing Ask ability. Maybe it would be better to have a (unique) ability called Random, with the same signature as Ask, to express intent. Or Choice maybe. (Note the existing Ask.provide function uses a handler that returns the same value on every call to ask, so the semantics are quite different to what the PRNG is doing.)

Loose end / discussion point

  • If I read it correctly (which I might well not have), I think the test library in base does its property-based testing by enumerating possible values from small to large (at least for the Nat domain, say). Would it be good if it used a PRNG to yield more far-flung values?

Things I still need to do

.me.base> display trunk.random.mersenne.TODO
  
  TODO...
   - debug failing test
   - add a test against a list of expected outputs
   - add Ask handler for Floats
   - comment that next assumes the state is seeded, or will crash
   - comment re considerations for seeding (time, location), helper to seed by time,
  default seed (replace that in mersenne.doc.examples)

  • move until to the right place
  • delete patches
  • update screenshot below

User docs

The main doc looks like this... [TODO update pic]

image

Code review

  The changes summarized below are available for you to review, using the following command:
  
    pull-request.load https://github.com/unisonweb/base https://github.com/atacratic/unisonweb-base.git
  
  Updates:
  
     patch trunk.patch (added 5 updates)
  
  Added definitions:
  
     type trunk.Nat32 (+3 metadata)
     type trunk.random.mersenne.State (+3 metadata)
     trunk.Nat32.Nat32                                  : Nat -> Nat32 (+3 metadata)
     trunk.random.mersenne.State.State                  : [Nat32] -> State (+2 metadata)
     trunk.Int.inRange                                  : Int
                                                        -> Int
                                                        -> Int
                                                        -> Boolean (+3 metadata)
     trunk.Int.inRange.doc                              : Doc (+2 metadata)
     trunk.Int.max                                      : Int -> Int -> Int (+2 metadata)
     trunk.Int.min                                      : Int -> Int -> Int (+2 metadata)
     trunk.Nat.inRange                                  : Nat
                                                        -> Nat
                                                        -> Nat
                                                        -> Boolean (+3 metadata)
     trunk.Nat.inRange.doc                              : Doc (+2 metadata)
     trunk.Nat.max                                      : Nat -> Nat -> Nat (+2 metadata)
     trunk.Nat.min                                      : Nat -> Nat -> Nat (+2 metadata)
     trunk.Nat32.*                                      : Nat32 -> Nat32 -> Nat32 (+2 metadata)
     trunk.Nat32.+                                      : Nat32 -> Nat32 -> Nat32 (+2 metadata)
     trunk.Nat32.<                                      : Nat32 -> Nat32 -> Boolean (+2 metadata)
     trunk.Nat32.<=                                     : Nat32 -> Nat32 -> Boolean (+2 metadata)
     trunk.Nat32.>                                      : Nat32 -> Nat32 -> Boolean (+2 metadata)
     trunk.Nat32.>=                                     : Nat32 -> Nat32 -> Boolean (+2 metadata)
     trunk.Nat32.Nat32.doc                              : Doc (+2 metadata)
     trunk.Nat32.and                                    : Nat32 -> Nat32 -> Nat32 (+3 metadata)
     trunk.Nat32.and.doc                                : Doc (+2 metadata)
     trunk.Nat32.bit                                    : Nat -> Nat32 (+3 metadata)
     trunk.Nat32.bit.doc                                : Doc (+2 metadata)
     trunk.Nat32.bit.test1                              : [Result] (+3 metadata)
     trunk.Nat32.bit.test2                              : [Result] (+3 metadata)
     trunk.Nat32.bit.test3                              : [Result] (+3 metadata)
     trunk.Nat32.clearBit                               : Nat32 -> Nat -> Nat32 (+4 metadata)
     trunk.Nat32.clearBit.doc                           : Doc (+3 metadata)
     trunk.Nat32.clearBit.test1                         : [Result] (+4 metadata)
     trunk.Nat32.clearBit.test2                         : [Result] (+4 metadata)
     trunk.Nat32.complement                             : Nat32 -> Nat32 (+3 metadata)
     trunk.Nat32.complement.doc                         : Doc (+2 metadata)
     trunk.Nat32.doc                                    : Doc (+3 metadata)
     trunk.Nat32.isEven                                 : Nat32 -> Boolean (+2 metadata)
     trunk.Nat32.maxNat32                               : Nat32 (+2 metadata)
     trunk.Nat32.maxNat32.test                          : [Result] (+3 metadata)
     trunk.Nat32.mkNat32                                : Nat -> Optional Nat32 (+2 metadata)
     trunk.Nat32.multiply.prop1                         : [Result] (+3 metadata)
     trunk.Nat32.plus.prop1                             : [Result] (+3 metadata)
     trunk.Nat32.shiftLeft                              : Nat32 -> Nat -> Nat32 (+2 metadata)
     trunk.Nat32.shiftLeft.prop1                        : [Result] (+3 metadata)
     trunk.Nat32.shiftRight                             : Nat32 -> Nat -> Nat32 (+2 metadata)
     trunk.Nat32.shiftRight.prop1                       : [Result] (+3 metadata)
     trunk.Nat32.toNat                                  : Nat32 -> Nat (+2 metadata)
     trunk.Nat32.truncate32                             : Nat -> Nat32 (+2 metadata)
     trunk.Nat32.truncate32.prop1                       : [Result] (+3 metadata)
     trunk.Nat32.truncate32.prop2                       : [Result] (+3 metadata)
     trunk.Nat32.xor                                    : Nat32 -> Nat32 -> Nat32 (+3 metadata)
     trunk.Nat32.xor.doc                                : Doc (+2 metadata)
     trunk.all                                          : (a ->{๐•–} Boolean)
                                                        ->{๐•–} [a]
                                                        ->{๐•–} Boolean (+2 metadata)
     trunk.any                                          : (a ->{๐•–} Boolean)
                                                        ->{๐•–} [a]
                                                        ->{๐•–} Boolean (+2 metadata)
     trunk.iterate                                      : Nat -> '{e} a ->{e} [a] (+3 metadata)
     trunk.iterate.doc                                  : Doc (+2 metadata)
     trunk.iterate.test                                 : [Result] (+3 metadata)
     trunk.metadata.authors.atacratic                   : Author
     trunk.metadata.authors.atacratic.guid              : GUID
     trunk.metadata.copyrightHolders.atacratic          : CopyrightHolder
     trunk.metadata.licenses.atacratic.mit_2020         : License
     trunk.none                                         : (a ->{๐•–} Boolean)
                                                        ->{๐•–} [a]
                                                        ->{๐•–} Boolean (+2 metadata)
     trunk.random.mersenne.State.doc                    : Doc (+2 metadata)
     trunk.random.mersenne.TODO                         : Doc (+2 metadata)
     trunk.random.mersenne.collect                      : '{Store State} x
                                                        -> Nat32
                                                        -> Nat
                                                        -> [x] (+3 metadata)
     trunk.random.mersenne.collect.doc                  : Doc (+3 metadata)
     trunk.random.mersenne.defaultSeed                  : Nat32 (+3 metadata)
     trunk.random.mersenne.defaultSeed.doc              : Doc (+2 metadata)
     trunk.random.mersenne.doc                          : Doc (+3 metadata)
     trunk.random.mersenne.doc.example1                 : [Nat] (+2 metadata)
     trunk.random.mersenne.doc.example2                 : Nat (+2 metadata)
     trunk.random.mersenne.handler                      : '{Store State} n
                                                        -> Nat32
                                                        -> Request (Ask n) a
                                                        -> a (+3 metadata)
     trunk.random.mersenne.handler.doc                  : Doc (+2 metadata)
     trunk.random.mersenne.int.next                     : '{Store State} Int (+3 metadata)
     trunk.random.mersenne.int.next.doc                 : Doc (+2 metadata)
     trunk.random.mersenne.int.nextFromRange            : Int
                                                        -> Int
                                                        -> '{Store State} Int (+3 metadata)
     trunk.random.mersenne.int.nextFromRange.doc        : Doc (+2 metadata)
     trunk.random.mersenne.int.nextFromRange.prop       : [Result] (+3 metadata)
     trunk.random.mersenne.nat.next                     : '{Store State} Nat (+3 metadata)
     trunk.random.mersenne.nat.next.doc                 : Doc (+2 metadata)
     trunk.random.mersenne.nat.nextFromRange            : Nat
                                                        -> Nat
                                                        -> '{Store State} Nat (+3 metadata)
     trunk.random.mersenne.nat.nextFromRange.doc        : Doc (+2 metadata)
     trunk.random.mersenne.nat.nextFromRange.doc.caveat : Doc (+2 metadata)
     trunk.random.mersenne.nat.nextFromRange.prop       : [Result] (+3 metadata)
     trunk.random.mersenne.nat32                        : Nat32
                                                        -> '{Ask Nat32} a
                                                        -> a (+3 metadata)
     trunk.random.mersenne.nat32.doc                    : Doc (+3 metadata)
     trunk.random.mersenne.nat32.handler                : Nat32
                                                        -> Request (Ask Nat32) a
                                                        -> a (+2 metadata)
     trunk.random.mersenne.next                         : '{Store State} Nat32 (+4 metadata)
     trunk.random.mersenne.next.doc                     : Doc (+3 metadata)
     trunk.random.mersenne.provide                      : '{Store State} n
                                                        -> Nat32
                                                        -> '{Ask n} a
                                                        -> a (+3 metadata)
     trunk.random.mersenne.provide.doc                  : Doc (+3 metadata)
     trunk.random.mersenne.seed                         : Nat32 ->{Store State} () (+3 metadata)
     trunk.random.mersenne.seed.doc                     : Doc (+3 metadata)
     trunk.random.mersenne.seed.tests.size              : [Result] (+4 metadata)
     trunk.random.mersenne.test.comparison              : โˆ€ (). () ->{IO} () (+4 metadata)
     trunk.random.mersenne.test.comparison.doc          : Doc (+3 metadata)
     trunk.random.mersenne.test.printOut                : [Nat] -> Nat ->{IO} () (+3 metadata)
     trunk.random.mersenne.test.printOut.doc            : Doc (+3 metadata)
     trunk.xor                                          : Boolean
                                                        -> Boolean
                                                        -> Boolean (+3 metadata)
     trunk.xor.doc                                      : Doc (+2 metadata)
     trunk.xor.test                                     : [Result] (+3 metadata)
     until                                              : (a ->{e} Boolean)
                                                        -> '{e} a
                                                        ->{e} a (+3 metadata)
     until.doc                                          : Doc (+2 metadata)
  
     patch trunk.random.patch (added 11 updates)

Various simple functions

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/emiflake/unison-emi.git:.prs.base._list_functions2

Added definitions:

 Either.mapLeft                  : (a ->{๐•–} b) -> Either a z ->{๐•–} Either b z (+1 metadata)
 Either.mapLeft.doc              : Doc (+2 metadata)
 Either.mapLeft.tests.ex1        : [Result] (+3 metadata)
 Either.mapRight                 : (a ->{๐•–} b) -> Either e a ->{๐•–} Either e b (+1 metadata)
 Either.mapRight.doc             : Doc (+2 metadata)
 Either.mapRight.tests.ex1       : [Result] (+3 metadata)
 List.lefts                      : [Either a b] -> [a] (+3 metadata)
 List.lefts.doc                  : Doc (+2 metadata)
 List.lefts.tests.ex1            : [Result] (+3 metadata)
 List.mapIndexed                 : (Nat ->{๐•–} a ->{๐•–} b) -> [a] ->{๐•–} [b] (+3 metadata)
 List.mapIndexed.doc             : Doc (+2 metadata)
 List.mapIndexed.tests.ex1       : [Result] (+3 metadata)
 List.mapIndexed.tests.ex2       : [Result] (+3 metadata)
 List.partitionEithers           : [Either a b] -> ([a], [b]) (+3 metadata)
 List.partitionEithers.doc       : Doc (+2 metadata)
 List.partitionEithers.tests.ex1 : [Result] (+3 metadata)
 List.rights                     : [Either a b] -> [b] (+3 metadata)
 List.rights.doc                 : Doc (+2 metadata)
 List.rights.tests.ex1           : [Result] (+3 metadata)
 List.singleton                  : a -> [a] (+1 metadata)
 List.singleton.doc              : Doc
 List.somes                      : [Optional a] -> [a] (+1 metadata)
 List.somes.doc                  : Doc (+2 metadata)
 List.somes.tests.ex1            : [Result] (+3 metadata)
 List.zipWith                    : (a ->{๐•–} b ->{๐•–} c)
                                 ->{๐•–} [a]
                                 ->{๐•–} [b]
                                 ->{๐•–} [c] (+3 metadata)
 List.zipWith.doc                : Doc (+2 metadata)
 List.zipWith.tests.edge1        : [Result] (+3 metadata)
 List.zipWith.tests.edge2        : [Result] (+3 metadata)
 List.zipWith.tests.edge3        : [Result] (+3 metadata)
 List.zipWith.tests.edge4        : [Result] (+3 metadata)
 List.zipWith.tests.ex1          : [Result] (+3 metadata)
 List.zipWith.tests.ex2          : [Result] (+3 metadata)
 List.zipWith.tests.zipWithRange : [Result] (+3 metadata)
 Tuple.pair                      : a -> b -> (a, b) (+3 metadata)
 Tuple.pair.doc                  : Doc (+2 metadata)

M1k release notes

Namespace hash: #q4cj5po5lk
Previous release M1j: #4rlr7npiqi

To get it:

.> pull https://github.com/unisonweb/base:.releases._M1k .base.M1k

What's changed since M1j

A bunch of definitions added by @runarorama @stew and @anovstrup:

.base> diff.namespace releases._M1j releases._M1k

Added definitions:

1.  ability Store a (+3 metadata)
2.  Store.get                         : {Store a} a (+3 metadata)
3.  Store.put                         : a ->{Store a} () (+3 metadata)
4.  Function.flatMap                  : (a -> r ->{e} b)
                                      -> (r ->{e} a)
                                      -> r
                                      ->{e} b (+3 metadata)
5.  Function.flatMap.doc              : Doc (+2 metadata)
6.  Int.and                           : Int -> Int -> Int
7.  Int.complement                    : Int -> Int -> Int
8.  Int.decrement                     : Int -> Int (+3 metadata)
9.  Int.decrement.doc                 : Doc (+2 metadata)
10. Int.decrement.test                : [Result] (+3 metadata)
11. Int.leadingZeros                  : Int -> Nat
12. Int.or                            : Int -> Int -> Int
13. Int.trailingZeros                 : Int -> Nat
14. Int.xor                           : Int -> Int -> Int
15. List.deleteAt                     : Nat -> [a] -> [a] (+3 metadata)
16. List.deleteAt.doc                 : Doc (+2 metadata)
17. List.deleteAt.test                : [Result] (+3 metadata)
18. List.foldr                        : (a ->{e} b ->{e} b) -> b -> [a] ->{e} b (+3 metadata)
19. List.foldr.doc                    : Doc (+2 metadata)
20. List.foldr.tests.homomorphism     : [Result] (+3 metadata)
21. Map.delete                        : k -> Map k v -> Map k v (+3 metadata)
22. Map.delete.doc                    : Doc (+2 metadata)
23. Map.delete.test                   : [Result] (+2 metadata)
24. Nat.and                           : Nat -> Nat -> Nat
25. Nat.complement                    : Nat -> Nat -> Nat
26. Nat.decrement                     : Nat -> Nat (+3 metadata)
27. Nat.decrement.doc                 : Doc (+2 metadata)
28. Nat.decrement.test                : [Result] (+3 metadata)
29. Nat.leadingZeros                  : Nat -> Nat
30. Nat.or                            : Nat -> Nat -> Nat
31. Nat.trailingZeros                 : Nat -> Nat
32. Nat.xor                           : Nat -> Nat -> Nat
33. Set.delete                        : k -> Set k -> Set k (+3 metadata)
34. Set.delete.doc                    : Doc (+2 metadata)
35. Set.delete.test                   : [Result] (+3 metadata)
36. Set.flatMap                       : (a ->{e} Set b) -> Set a ->{e} Set b (+3 metadata)
37. Set.flatMap.doc                   : Doc (+2 metadata)
38. Set.flatMap.tests.associative     : [Result] (+3 metadata)
39. Set.flatMap.tests.unit            : [Result] (+3 metadata)
40. Set.flatten                       : Set (Set b) -> Set b (+3 metadata)
41. Set.flatten.doc                   : Doc (+2 metadata)
42. Set.flatten.tests.associative     : [Result] (+3 metadata)
43. Set.flatten.tests.unit            : [Result] (+3 metadata)
44. Set.foldl                         : (b ->{e} a ->{e} b) -> b -> Set a ->{e} b (+3 metadata)
45. Set.foldl.doc                     : Doc (+2 metadata)
46. Set.foldl.tests.homomorphism      : [Result] (+3 metadata)
47. Set.foldr                         : (a ->{e} b ->{e} b) -> b -> Set a ->{e} b (+3 metadata)
48. Set.foldr.doc                     : Doc (+2 metadata)
49. Set.foldr.tests.homomorphism      : [Result] (+3 metadata)
50. Set.map                           : (a ->{e} b) -> Set a ->{e} Set b (+3 metadata)
51. Set.map.doc                       : Doc (+2 metadata)
52. Set.map.test                      : [Result] (+3 metadata)
53. Set.singleton                     : a -> Set a (+3 metadata)
54. Set.singleton.doc                 : Doc (+2 metadata)
55. Set.singleton.test                : [Result] (+3 metadata)
56. Set.unions                        : [Set a] -> Set a (+3 metadata)
57. Set.unions.doc                    : Doc (+2 metadata)
58. Set.unions.test                   : [Result] (+3 metadata)
59. Store.doc                         : Doc (+2 metadata)
43. Set.flatten.tests.unit            : [Result] (+3 metadata)
44. Set.foldl                         : (b ->{e} a ->{e} b) -> b -> Set a ->{e} b (+3 metadata)
45. Set.foldl.doc                     : Doc (+2 metadata)
46. Set.foldl.tests.homomorphism      : [Result] (+3 metadata)
47. Set.foldr                         : (a ->{e} b ->{e} b) -> b -> Set a ->{e} b (+3 metadata)
48. Set.foldr.doc                     : Doc (+2 metadata)
49. Set.foldr.tests.homomorphism      : [Result] (+3 metadata)
50. Set.map                           : (a ->{e} b) -> Set a ->{e} Set b (+3 metadata)
51. Set.map.doc                       : Doc (+2 metadata)
52. Set.map.test                      : [Result] (+3 metadata)
53. Set.singleton                     : a -> Set a (+3 metadata)
54. Set.singleton.doc                 : Doc (+2 metadata)
55. Set.singleton.test                : [Result] (+3 metadata)
56. Set.unions                        : [Set a] -> Set a (+3 metadata)
57. Set.unions.doc                    : Doc (+2 metadata)
58. Set.unions.test                   : [Result] (+3 metadata)
59. Store.doc                         : Doc (+2 metadata)
60. Store.get.doc                     : Doc (+3 metadata)
61. Store.get.examples.ex1            : Nat (+2 metadata)
62. Store.local                       : a -> '{g, Store a} v ->{g, Store a} v (+3 metadata)
63. Store.local.doc                   : Doc (+3 metadata)
64. Store.local.examples.ex1          : (Nat, Nat, Nat) (+2 metadata)
65. Store.local.test                  : [Result] (+3 metadata)
66. Store.modify                      : (a ->{g} a) ->{g, Store a} () (+3 metadata)
67. Store.modify.doc                  : Doc (+3 metadata)
68. Store.modify.examples.increment   : Nat (+3 metadata)
69. Store.modify.test                 : [Result] (+3 metadata)
70. Store.put.doc                     : Doc (+3 metadata)
71. Store.put.examples.ex1            : Nat (+2 metadata)
72. Store.withInitialValue            : a -> '{g, Store a} v ->{g} v (+4 metadata)
73. Store.withInitialValue.doc        : Doc (+3 metadata)
74. Store.withInitialValue.handler    : a -> Request (Store a) v -> v (+2 metadata)
75. Store.withInitialValue.laws.law1  : a ->{Store a} Test (+2 metadata)
76. Store.withInitialValue.tests.law1 : [Result] (+3 metadata)
77. test.mapOf                        : '{Gen} k -> '{Gen} v -> '{Gen} Map k v (+3 metadata)
78. test.mapOf.doc                    : Doc (+2 metadata)
79. test.pairOf                       : '{Gen} a -> '{Gen} b -> '{Gen} (a, b) (+3 metadata)
80. test.pairOf.doc                   : Doc (+2 metadata)

Name changes:

Original            Changes
81. test.list       82. test.listOf (added)
                    83. test.list (removed)

84. test.set        85. test.setOf (added)
                    86. test.set (removed)

87. test.set.doc    88. test.setOf.doc (added)
                    89. test.set.doc (removed)

Add a whole bunch of functionality to base

This also changes the type of List.init to be in line with List.head, List.tail, etc.

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base https://github.com/runarorama/base

Updates:

 List.init : [a] -> [a]
 โ†“
 List.init : [a] -> Optional [a]
 +  unisoncomputing2020 : License
 +  dolio               : Author

 List.powerslice : [a] -> [[a]]
 โ†“
 List.powerslice : [a] -> [[a]]
 +  unisoncomputing2020 : License
 +  dolio               : Author

 Nat.drop : Nat -> Nat -> Nat
 +  Nat.drop.doc : Doc

Added definitions:

 Char.toText                           : Char -> Text
 Float.pi                              : Float
 โ”Œ Int.^                               : Int -> Nat -> Int
 โ”” Int.pow                             : Int -> Nat -> Int
 Int.abs                               : Int -> Nat
 Int.decrement                         : Nat -> Int
 List.adjacentPairs                    : [a] -> [(a, a)]
 List.all                              : (a ->{e} Boolean)
                                       -> [a]
                                       ->{e} Boolean
 List.any                              : (a ->{e} Boolean)
                                       -> [a]
                                       ->{e} Boolean
 List.break                            : (a ->{e} Boolean)
                                       -> [a]
                                       ->{e} ([a], [a]) (+1 metadata)
 List.chunk                            : Nat -> [a] -> [[a]]
 List.chunksOf                         : Nat -> [a] -> [[a]]
 List.concatenate                      : [[a]] -> [a]
 List.dropRight                        : Nat -> [a] -> [a] (+2 metadata)
 List.dropRight.doc                    : Doc (+1 metadata)
 List.dropRight.examples.ex1           : [Nat] (+1 metadata)
 List.dropRight.test                   : [Result] (+2 metadata)
 List.dropWhile                        : (a ->{e} Boolean) -> [a] ->{e} [a]
 List.filter                           : (a ->{e} Boolean) -> [a] ->{e} [a]
 List.filter.tests.constFalseIsEmpty   : [Result] (+2 metadata)
 List.filter.tests.constTrueIsIdentity : [Result] (+2 metadata)
 โ”Œ List.first                          : [a] -> Optional a
 โ”” List.head                           : [a] -> Optional a
 List.head.tests.headOfCons            : [Result] (+1 metadata)
 List.head.tests.headOfEmpty           : [Result] (+1 metadata)
 List.init.tests.initOfEmpty           : [Result] (+1 metadata)
 List.init.tests.initOfSnoc            : [Result] (+1 metadata)
 List.intercalate                      : [a] -> [[a]] -> [a]
 List.intersect                        : [a] -> [a] -> [a] (+1 metadata)
 List.intersect.tests.spec             : [Result] (+2 metadata)
 List.intersectBy                      : (a ->{e} a ->{e} Boolean)
                                       -> [a]
                                       -> [a]
                                       ->{e} [a]
 List.intersperse                      : a -> [a] -> [a]
 List.isEmpty                          : [a] -> Boolean
 List.isEmpty.tests.consIsNonempty     : [Result] (+1 metadata)
 List.isEmpty.tests.emptyIsEmpty       : [Result] (+1 metadata)
 List.iterate                          : Nat -> (a ->{๐•–} a) -> a ->{๐•–} [a]
 List.iterateUntil                     : (a ->{๐•–} Boolean)
                                       -> (a ->{๐•–} a)
                                       -> a
                                       ->{๐•–} [a]
 List.iterateWhile                     : (a ->{๐•–} Boolean)
                                       -> (a ->{๐•–} a)
                                       -> a
                                       ->{๐•–} [a]
 List.last                             : [a] -> Optional a
 List.last.tests.lastOfEmpty           : [Result] (+1 metadata)
 List.last.tests.lastOfSnoc            : [Result] (+1 metadata)
 List.minus                            : [a] -> [a] -> [a] (+1 metadata)
 List.replicate                        : Nat -> a -> [a]
 List.replicate.tests.length           : [Result] (+1 metadata)
 List.scanLeft                         : (b -> a ->{e} b)
                                       -> b
                                       -> [a]
                                       ->{e} [b]
 List.scanRight                        : (a -> b ->{e} b)
                                       -> b
                                       -> [a]
                                       ->{e} [b]
 List.span                             : (a ->{e} Boolean)
                                       -> [a]
                                       ->{e} ([a], [a])
 List.splitAt                          : Nat -> [a] -> ([a], [a])
 List.tail                             : [a] -> Optional [a]
 List.tail.tests.tailOfCons            : [Result] (+1 metadata)
 List.tail.tests.tailOfEmpty           : [Result] (+1 metadata)
 List.takeWhile                        : (a ->{๐•–} Boolean) -> [a] ->{๐•–} [a]
 List.tests.gens.nonEmpty              : '{Gen} [Nat]
 โ”Œ Nat.^                               : Nat -> Nat -> Nat
 โ”” Nat.pow                             : Nat -> Nat -> Nat
 Nat.decrement                         : Nat -> Nat
 Nat.drop.doc                          : Doc
 Nat.drop.examples.ex1                 : Nat
 Nat.drop.examples.ex2                 : Nat
 Nat.pow.tests.expansion               : [Result] (+2 metadata)
 Nat.pow.tests.homomorphism            : [Result] (+1 metadata)
 Nat.tests.gens.smallNat               : '{Gen} Nat
 Nat.times                             : Nat -> (a ->{e} a) -> a ->{e} a
 Optional.join                         : Optional (Optional a) -> Optional a
 Optional.toList                       : Optional a -> [a]
 Search.findIndex                      : (a ->{e} Boolean)
                                       -> [a]
                                       ->{e} Optional Nat
 Search.findLastIndex                  : (a ->{๐•–} Boolean)
                                       -> [a]
                                       ->{๐•–} Optional Nat
 Text.chunksOf                         : Nat -> Text -> [Text]
 Text.cons                             : Char -> Text -> Text
 Text.fromBytes                        : Bytes -> Text
 Text.join                             : Text -> [Text] -> Text
 Text.length                           : Text -> Nat
 Text.snoc                             : Text -> Char -> Text
 Text.split                            : Text -> Text -> [Text]
 Text.startsWith                       : Text -> Text -> Boolean
 Text.toBytes                          : Text -> Bytes
 Tuple.curry                           : ((a, b) ->{๐•–} c) -> a -> b ->{๐•–} c
 Tuple.uncurry                         : (a ->{๐•–} b ->{๐•–} c) -> (a, b) ->{๐•–} c
 Universal.!=                          : a -> a -> Boolean
 Universal.max                         : a -> a -> a
 Universal.min                         : a -> a -> a
 asTypeOf                              : a -> a -> a
 bind                                  : (a ->{๐•–} b ->{๐•–} c)
                                       -> (b ->{๐•–} a)
                                       -> b
                                       ->{๐•–} c
 contains                              : [a] -> a -> Boolean (+1 metadata)
 flip                                  : (a ->{๐•–} b ->{๐•–} c) -> b -> a ->{๐•–} c
 fuse                                  : (r ->{๐•–} a ->{๐•–} b)
                                       -> (r ->{๐•–} a)
                                       -> r
                                       ->{๐•–} b
 until                                 : (a ->{e} Boolean)
                                       -> (a ->{e} a)
                                       -> a
                                       ->{e} a
 while                                 : (a ->{e} Boolean)
                                       -> (a ->{e} a)
                                       -> a
                                       ->{e} a
 xor                                   : Boolean -> Boolean -> Boolean

 patch List.patch (added 1 updates)
 patch patch (added 27 updates)

Boolean.implies etc, List.contains/isInfixOf etc, List.tail, while, etc

Misc functions for base.

Plus changing List.init to return Optional (to distinguish between the cases where the input is empty vs has size 1.)

Includes some requests of @runarorama's from other tickets.

FYI @dariooddenino

Code review

  The changes summarized below are available for you to review, using the following command:
  
    pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/atacratic/unison-playpen:._base.prs._2
  
  Updates:
  
     List.init : [a] -> [a]
     โ†“
     List.init : [a] -> Optional [a]
     +  unisoncomputing2020 : License
     +  dolio               : Author
     +  atacratic.mit_2020  : License
     +  authors.atacratic   : Author
    
     List.powerslice : [a] -> [[a]]
     โ†“
     List.powerslice : [a] -> [[a]]
     +  unisoncomputing2020 : License
     +  powerslice.doc      : Doc
     +  dolio               : Author
     +  atacratic.mit_2020  : License
     +  authors.atacratic   : Author
  
     patch patch (added 2 updates)
  
  Added definitions:
  
     Boolean.given                   : Boolean -> Boolean -> Boolean (+3 metadata)
     Boolean.given.doc               : Doc (+2 metadata)
     Boolean.given.test              : [Result] (+3 metadata)
     Boolean.implies                 : Boolean -> Boolean -> Boolean (+3 metadata)
     Boolean.implies.doc             : Doc (+2 metadata)
     Boolean.implies.test            : [Result] (+3 metadata)
     List.concatOptional             : Optional [a] -> [a] (+3 metadata)
     List.concatOptional.doc         : Doc (+2 metadata)
     List.concatOptional.tests.prop1 : [Result] (+3 metadata)
     List.concatOptional.tests.test1 : [Result] (+3 metadata)
     List.contains                   : a -> [a] -> Boolean (+3 metadata)
     List.contains.doc               : Doc (+2 metadata)
     List.contains.tests.prop1       : [Result] (+3 metadata)
     List.contains.tests.test1       : [Result] (+3 metadata)
     List.contains.tests.test2       : [Result] (+3 metadata)
     List.isInfixOf                  : [a] -> [a] -> Boolean (+3 metadata)
     List.isInfixOf.doc              : Doc (+2 metadata)
     List.isInfixOf.tests.prop1      : [Result] (+3 metadata)
     List.isPrefixOf                 : [a] -> [a] -> Boolean (+3 metadata)
     List.isPrefixOf.doc             : Doc (+2 metadata)
     List.isPrefixOf.tests.prop1     : [Result] (+3 metadata)
     List.isPrefixOf.tests.prop2     : [Result] (+3 metadata)
     List.isSuffixOf                 : [a] -> [a] -> Boolean (+3 metadata)
     List.isSuffixOf.doc             : Doc (+2 metadata)
     List.isSuffixOf.tests.prop1     : [Result] (+3 metadata)
     List.isSuffixOf.tests.prop2     : [Result] (+3 metadata)
     List.powerslice.doc             : Doc (+2 metadata)
     List.powerslice.examples.ex1    : [[Nat]] (+2 metadata)
     List.powerslice.examples.ex2    : [[a]] (+2 metadata)
     List.powerslice.tests.prop1     : [Result] (+3 metadata)
     List.powerslice.tests.test1     : [Result] (+3 metadata)
     List.tail                       : [a] -> Optional [a] (+3 metadata)
     List.tail.doc                   : Doc (+2 metadata)
     List.tail.tests.prop1           : [Result] (+3 metadata)
     List.tail.tests.test1           : [Result] (+3 metadata)
     List.tail.tests.test2           : [Result] (+3 metadata)
     absurdly                        : '{e} Void ->{e} a (+2 metadata)
     while                           : (a ->{e} Boolean) -> '{e} a ->{e} a (+3 metadata)
     while.doc                       : Doc (+2 metadata)
     while.test                      : [Result] (+3 metadata)

Add new builtins

Closed in 5a5d057 which is Unison namespace hash: 5c6etkeuhfggluiv4tamdkhagnidll716p5a52cigmsng5aa343jcq327

Added the new builtins that @stew added on Int/Nat:

.newbuiltins> builtins.merge

  Done.

.newbuiltins> ls

  1. base/    (661 definitions)
  2. builtin/ (156 definitions)
  3. merged/  (661 definitions)

.newbuiltins> merge builtin 3

  Here's what's changed in .newbuiltins.merged after the merge:
  
  Added definitions:
  
    1. Int.pow        : Int -> Nat -> Int
    2. Int.shiftLeft  : Int -> Nat -> Int
    3. Int.shiftRight : Int -> Nat -> Int
    4. Nat.pow        : Nat -> Nat -> Nat
    5. Nat.shiftLeft  : Nat -> Nat -> Nat
    6. Nat.shiftRight : Nat -> Nat -> Nat
  
  Tip: You can use `todo` to see if this generated any work to do in this namespace and `test` to
       run the tests. Or you can use `undo` or `reflog` to undo the results of this merge.

.newbuiltins> cd merged
.newbuiltins.merged> push [email protected]:unisonweb/base

Add two new generators

This adds generators for Lists with at least one element, as well as Sets.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base https://github.com/runarorama/base:.addGens

Added definitions:

 test.v1.gen.List.nonEmpty     : '{Gen} [Nat] (+3 metadata)
 test.v1.gen.List.nonEmpty.doc : Doc (+2 metadata)
 test.v1.set                   : '{Gen} a -> '{Gen} Set a (+3 metadata)
 test.v1.set.doc               : Doc (+2 metadata)

Additional list functions

Added a bunch of list functions that were missing.
Some docs are heavily inspired by the haskell counterpart, not sure if this could be an issue for the license.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/dariooddenino/unisoncode:.prs.base._listextra

Added definitions:

 List.dropWhile                       : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} [a] (+3 metadata)
 List.dropWhile.doc                   : Doc (+2 metadata)
 List.dropWhile.tests.all             : [Result] (+3 metadata)
 List.dropWhile.tests.middle          : [Result] (+3 metadata)
 List.dropWhile.tests.none            : [Result] (+3 metadata)
 List.group                           : [a] -> [[a]] (+3 metadata)
 List.group.doc                       : Doc (+2 metadata)
 List.group.tests.base                : [Result] (+3 metadata)
 List.groupBy                         : (a ->{๐•–} a ->{๐•–} Boolean)
                                      ->{๐•–} [a]
                                      ->{๐•–} [[a]] (+3 metadata)
 List.groupBy.doc                     : Doc (+2 metadata)
 List.intercalate                     : [a] -> [[a]] -> [a] (+3 metadata)
 List.intercalate.doc                 : Doc (+2 metadata)
 List.intercalate.tests.empty         : [Result] (+3 metadata)
 List.intercalate.tests.empty1        : [Result] (+3 metadata)
 List.intercalate.tests.empty2        : [Result] (+3 metadata)
 List.intercalate.tests.simple        : [Result] (+3 metadata)
 List.intercalate.tests.size          : [Result] (+3 metadata)
 List.intercalateMap                  : (a ->{๐•–} [b]) -> [b] -> [a] ->{๐•–} [b] (+3 metadata)
 List.intercalateMap.doc              : Doc (+2 metadata)
 List.intercalateMap.tests.simple     : [Result] (+3 metadata)
 List.maximum                         : [a] -> Optional a (+3 metadata)
 List.maximum.doc                     : Doc (+2 metadata)
 List.maximum.tests.base              : [Result] (+3 metadata)
 List.maximum.tests.empty             : [Result] (+3 metadata)
 List.minimum                         : [a] -> Optional a (+3 metadata)
 List.minimum.doc                     : Doc (+2 metadata)
 List.minimum.tests.base              : [Result] (+3 metadata)
 List.nonEmptySubsequences            : [a] -> [[a]] (+3 metadata)
 List.nonEmptySubsequences.doc        : Doc (+2 metadata)
 List.nonEmptySubsequences.tests.base : [Result] (+3 metadata)
 List.span                            : (a ->{๐•–} Boolean)
                                      ->{๐•–} [a]
                                      ->{๐•–} ([a], [a]) (+3 metadata)
 List.span.doc                        : Doc (+2 metadata)
 List.span.tests.alle                 : [Result] (+3 metadata)
 List.span.tests.allf                 : [Result] (+3 metadata)
 List.span.tests.middle               : [Result] (+3 metadata)
 List.split                           : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} [[a]] (+3 metadata)
 List.split.doc                       : Doc (+2 metadata)
 List.split.tests.base                : [Result] (+3 metadata)
 List.split.tests.double              : [Result] (+3 metadata)
 List.split.tests.empty               : [Result] (+3 metadata)
 List.splitAt                         : Nat -> [a] -> ([a], [a]) (+3 metadata)
 List.splitAt.doc                     : Doc (+2 metadata)
 List.splitAt.tests.base              : [Result] (+3 metadata)
 List.splitAt.tests.ob                : [Result] (+3 metadata)
 List.splitAt.tests.zero              : [Result] (+3 metadata)
 List.stripPrefix                     : [a] ->{๐•–} [a] ->{๐•–} Optional [a] (+3 metadata)
 List.stripPrefix.all                 : [Result] (+3 metadata)
 List.stripPrefix.base                : [Result] (+3 metadata)
 List.stripPrefix.doc                 : Doc (+2 metadata)
 List.stripPrefix.none                : [Result] (+3 metadata)
 List.subsequences                    : [a] -> [[a]] (+3 metadata)
 List.subsequences.doc                : Doc (+2 metadata)
 List.subsequences.tests.base         : [Result] (+3 metadata)
 List.takeWhile                       : (a ->{๐•–} Boolean) ->{๐•–} [a] ->{๐•–} [a] (+3 metadata)
 List.takeWhile.doc                   : Doc (+2 metadata)
 List.takeWhile.tests.all             : [Result] (+3 metadata)
 List.takeWhile.tests.middle          : [Result] (+3 metadata)
 List.takeWhile.tests.none            : [Result] (+3 metadata)

Store ability

This PR adds a Store ability and associated functions (modify, local, and a store handler).

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/anovstrup/unisonweb-base:.prs._storePR

Added definitions:

 ability Store a (+3 metadata)
 Store.get                         : {Store a} a (+3 metadata)
 Store.put                         : a ->{Store a} () (+3 metadata)
 Store.doc                         : Doc (+2 metadata)
 Store.get.doc                     : Doc (+3 metadata)
 Store.get.examples.ex1            : Nat (+2 metadata)
 Store.local                       : a -> '{g, Store a} v ->{g, Store a} v (+3 metadata)
 Store.local.doc                   : Doc (+3 metadata)
 Store.local.examples.ex1          : (Nat, Nat, Nat) (+2 metadata)
 Store.local.test                  : [Result] (+3 metadata)
 Store.modify                      : (a ->{g} a) ->{g, Store a} () (+3 metadata)
 Store.modify.doc                  : Doc (+3 metadata)
 Store.modify.examples.increment   : Nat (+3 metadata)
 Store.modify.test                 : [Result] (+3 metadata)
 Store.put.doc                     : Doc (+3 metadata)
 Store.put.examples.ex1            : Nat (+2 metadata)
 Store.withInitialValue            : a -> '{g, Store a} v ->{g} v (+4 metadata)
 Store.withInitialValue.doc        : Doc (+3 metadata)
 Store.withInitialValue.handler    : a -> Request (Store a) v -> v (+2 metadata)
 Store.withInitialValue.laws.law1  : a ->{Store a} Test (+2 metadata)
 Store.withInitialValue.tests.law1 : [Result] (+3 metadata)

Widen some type signatures in test.v1

Widens the type signatures of Gen.toWeighted, runs, and sample in the test framework so that they work with generators that have arbitrary effects.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.test.v1 https://github.com/runarorama/testv1

Updates:

 Gen.toWeighted : '{Gen} a -> Weighted a
 โ†“
 Gen.toWeighted : '{e, Gen} a ->{e} Weighted a
 +  unisoncomputing2020 : License
 +  runarorama          : Author

 runs : Nat -> '{Gen} Test -> [Result]
 โ†“
 runs : Nat -> '{e, Gen} Test ->{e} [Result]
 +  unisoncomputing2020 : License
 +  runarorama          : Author

 sample : Nat -> '{Gen} a -> [a]
 โ†“
 sample : Nat -> '{e, Gen} a ->{e} [a]
 +  unisoncomputing2020 : License
 +  runarorama          : Author

There were 25 auto-propagated updates.

Add Heather Miller as author

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk.metadata.authors https://github.com/runarorama/mybase:.hm

Added definitions:

 heathermiller      : Author
 heathermiller.guid : GUID

existent, unison implementation of `List.empty`

Replaces the reference to unimplemented builtin ##List.empty with a reference to the term [].

Quick fix for unisonweb/unison#1338

.temp> view base.List.empty head.List.empty

  -- base.List.empty is built-in.
  
  head.List.empty : [a]
  head.List.empty = []

The changes summarized below are available for you to review, using the following
command:

pull-request.load https://github.com/unisonweb/base https://github.com/aryairani/base

Updates:

 List.empty : [a]
 โ†“
 List.empty : [a]

Added definitions:

 patch patch (added 1 updates)

Adds testing helper, natIn documentation, Char generators.

Overview

This unison pull request aims to add Generators in the base.test.v1.Char namespace, and also adds documentation to the base.test.v1.natIn generator.

Implementation notes

  1. adds (===) aliased to equalsOrBug. This allows testing with === that breaks immediately with debug output of the values being compared. The documentation contains an example of the behaviour.
  2. add documentation to natIn
  3. adds a natIn' generator, with examples and documentation, that allows a rolling over to the start version of natIn.
  4. adds generators for alpha, ascii, asciiNonPrintable, asciiPrintable, digit, hexDigit, upper, lower (all with examples and linked documentation)

Controversial (?)

I now realise that === should have been one PR, natIn documentation another, and the Char.* generators another still. This was not intentional, and in hindsight probably down to not being as familiar as I should be with namespacing, will do my utmost to avoid scope creep in the future.

Test coverage

All the methods implemented have been tested, and the evaluated values in the documentation have been produced via sampling the generators.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.test.v1 https://github.com/pete-ts/base:.base.test.v1

Updates:

 natIn : Nat -> Nat -> '{Gen} Nat
 +  natIn.doc : Doc

Added definitions:

 โ”Œ ===                                : a -> a -> Boolean (+1 metadata)
 โ”” equalsOrBug                        : a -> a -> Boolean (+1 metadata)
 Char.alpha                           : '{Gen} Char (+2 metadata)
 Char.alpha.doc                       : Doc
 Char.alpha.examples.some             : [Char]
 Char.ascii                           : '{Gen} Char (+1 metadata)
 Char.ascii.doc                       : Doc (+1 metadata)
 Char.ascii.examples.some             : [Char]
 Char.asciiNonPrintable               : '{Gen} Char (+1 metadata)
 Char.asciiNonPrintable.doc           : Doc
 Char.asciiNonPrintable.examples.some : [Char]
 Char.asciiPrintable                  : '{Gen} Char (+2 metadata)
 Char.asciiPrintable.doc              : Doc
 Char.asciiPrintable.examples.some    : [Char]
 Char.digit                           : '{Gen} Char (+2 metadata)
 Char.digit.doc                       : Doc
 Char.digit.examples.all              : [Char]
 Char.hexDigit                        : '{Gen} Char (+1 metadata)
 Char.hexDigit.doc                    : Doc
 Char.hexDigit.examples.some          : [Char]
 Char.lower                           : '{Gen} Char (+2 metadata)
 Char.lower.doc                       : Doc
 Char.lower.examples.some             : [Char]
 Char.upper                           : '{Gen} Char (+2 metadata)
 Char.upper.doc                       : Doc
 Char.upper.examples.some             : [Char]
 equalsOrBug.doc                      : Doc
 natIn'                               : Nat -> Nat -> '{Gen} Nat (+1 metadata)
 natIn'.doc                           : Doc (+1 metadata)
 natIn'.examples.oneOneTenTimes       : [Nat] (+1 metadata)
 natIn'.examples.oneTenTenTimes       : [Nat] (+1 metadata)
 natIn'.examples.zeroOneOnce          : [Nat] (+1 metadata)
 natIn'.examples.zeroOneTenTimes      : [Nat] (+1 metadata)
 natIn.doc                            : Doc
 natIn.examples.oneOneTenTimes        : [Nat]
 natIn.examples.oneTenTenTimes        : [Nat]
 natIn.examples.zeroOneOnce           : [Nat]
 natIn.examples.zeroOneTenTimes       : [Nat]

 patch Char.patch (added 9 updates)
 patch patch (added 10 updates)

Universal min, max, and Ordering

This PR adds Universal.min and Universal.max which uses universal ordering. Also adds the Ordering type and supporting functions.

Potentially controversial decisions:

  • Deleted Int.min, Int.max, Nat.min and Nat.max as these have the same implementation as Universal.min and Universal.max.
  • Added patch entries for these replacements as well.
  • Moved some of the tests over to under the Universal namespace but deleted redundant others.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/runarorama/mybase:._topic.ordering

Updates:

 patch patch (added 4 updates)

Added definitions:

 unique type Ordering (+3 metadata)
 Ordering.Equal                         : Ordering
 Ordering.Greater                       : Ordering
 Ordering.Less                          : Ordering
 Ordering.andThen                       : Ordering
                                        -> Ordering
                                        -> Ordering (+3 metadata)
 Ordering.andThen.doc                   : Doc (+2 metadata)
 Ordering.andThen.example.ex1           : Ordering (+2 metadata)
 Ordering.doc                           : Doc (+2 metadata)
 Universal.compareOn                    : (a ->{e} x)
                                        -> a
                                        -> a
                                        ->{e} Ordering (+3 metadata)
 Universal.compareOn.doc                : Doc (+2 metadata)
 Universal.max                          : a -> a -> a (+3 metadata)
 Universal.max.doc                      : Doc (+2 metadata)
 Universal.max.tests.absorption         : [Test.Result] (+2 metadata)
 Universal.max.tests.associative        : [Test.Result] (+4 metadata)
 Universal.max.tests.commutative        : [Test.Result] (+4 metadata)
 Universal.max.tests.distributesOverMin : [Test.Result] (+2 metadata)
 Universal.max.tests.idempotent         : [Test.Result] (+2 metadata)
 Universal.max.tests.partialOrder       : [Test.Result] (+4 metadata)
 Universal.min                          : a -> a -> a (+3 metadata)
 Universal.min.doc                      : Doc (+2 metadata)
 Universal.min.tests.absorption         : [Test.Result] (+4 metadata)
 Universal.min.tests.associative        : [Test.Result] (+3 metadata)
 Universal.min.tests.commutative        : [Test.Result] (+3 metadata)
 Universal.min.tests.distributesOverMax : [Test.Result] (+2 metadata)
 Universal.min.tests.idempotent         : [Test.Result] (+2 metadata)
 Universal.min.tests.partialOrder       : [Test.Result] (+2 metadata)
 Universal.ordering                     : a -> a -> Ordering (+3 metadata)
 Universal.ordering.doc                 : Doc (+2 metadata)
 Universal.ordering.doc.snippet1        : Doc (+2 metadata)

Removed definitions:

 Int.max                           : Int -> Int -> Int
 Int.max.doc                       : Doc
 โ”Œ Int.max.tests.absorption        : [Test.Result]
 โ”” Int.min.tests.absorption
 Int.max.tests.associative         : [Test.Result]
 Int.max.tests.commutative         : [Test.Result]
 Int.max.tests.deMorgan            : [Test.Result]
 Int.max.tests.distributesOverMin  : [Test.Result]
 Int.max.tests.idempotent          : [Test.Result]
 Int.max.tests.partialOrder        : [Test.Result]
 Int.max.tests.top                 : [Test.Result]
 Int.min                           : Int -> Int -> Int
 Int.min.doc                       : Doc
 Int.min.tests.associative         : [Test.Result]
 Int.min.tests.bottom              : [Test.Result]
 Int.min.tests.commutative         : [Test.Result]
 Int.min.tests.deMorgan            : [Test.Result]
 Int.min.tests.distributesOverMax  : [Test.Result]
 Int.min.tests.idempotent          : [Test.Result]
 Int.min.tests.partialOrder        : [Test.Result]
 Nat.max                           : Nat -> Nat -> Nat
 Nat.max.doc                       : Doc
 Nat.max.tests.absorption          : [Test.Result]
 Nat.max.tests.additionDistributes : [Test.Result]
 Nat.max.tests.associative         : [Test.Result]
 Nat.max.tests.commutative         : [Test.Result]
 Nat.max.tests.distributesOverMin  : [Test.Result]
 Nat.max.tests.idempotent          : [Test.Result]
 Nat.max.tests.identity            : [Test.Result]
 Nat.max.tests.partialOrder        : [Test.Result]
 โ”Œ Nat.max.tests.summation         : [Test.Result]
 โ”” Nat.min.tests.summation
 Nat.min                           : Nat -> Nat -> Nat
 Nat.min.doc                       : Doc
 Nat.min.tests.additionDistributes : [Test.Result]
 Nat.min.tests.associative         : [Test.Result]
 Nat.min.tests.commutative         : [Test.Result]
 Nat.min.tests.distributesOverMax  : [Test.Result]
 Nat.min.tests.idempotent          : [Test.Result]
 Nat.min.tests.identity            : [Test.Result]
 Nat.min.tests.partialOrder        : [Test.Result]

Adds List.intersperse

This pull request adds List.intersperse. Hope everything's fine!

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/dariooddenino/unisoncode:.prs.base._intersperse

Updates:

 patch patch (added 1 updates)

Added definitions:

 List.intersperse                             : a -> [a] -> [a] (+1 metadata)
 List.intersperse.doc                         : Doc
 List.intersperse.tests.base                  : [Result] (+1 metadata)
 List.intersperse.tests.empty                 : [Result] (+1 metadata)
 List.metadata.authors.dariooddenino          : Author
 List.metadata.authors.dariooddenino.guid     : GUID
 List.metadata.copyrightHolders.dariooddenino : CopyrightHolder
 metadata.authors.dariooddenino               : Author
 metadata.authors.dariooddenino.guid          : GUID
 metadata.copyrightHolders.dariooddenino      : CopyrightHolder
 metadata.licenses.dariooddenino2020          : License (+1 metadata)

Add some basic operations on Set, Map, List

This adds a number of missing operations on functions, Set, List, and Map, along with associated docs.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load [email protected]:unisonweb/base.git:.trunk [email protected]:runarorama/mybase.git:.prs._pr27

Added definitions:

 Function.flatMap     : (a -> r ->{e} b) -> (r ->{e} a) -> r ->{e} b (+3 metadata)
 Function.flatMap.doc : Doc (+2 metadata)
 List.deleteAt        : Nat -> [a] -> [a] (+3 metadata)
 List.deleteAt.doc    : Doc (+2 metadata)
 List.deleteAt.test   : [Result] (+3 metadata)
 Map.delete           : k -> Map k v -> Map k v (+3 metadata)
 Map.delete.doc       : Doc (+2 metadata)
 Map.delete.test      : [Result] (+2 metadata)
 Set.delete           : k -> Set k -> Set k (+3 metadata)
 Set.delete.doc       : Doc (+2 metadata)
 Set.delete.test      : [Result] (+3 metadata)
 Set.map              : (a ->{e} b) -> Set a ->{e} Set b (+3 metadata)
 Set.map.doc          : Doc (+2 metadata)
 Set.map.test         : [Result] (+3 metadata)
 Set.singleton        : a -> Set a (+3 metadata)
 Set.singleton.doc    : Doc (+2 metadata)
 Set.singleton.test   : [Result] (+3 metadata)
 test.mapOf           : '{Gen} k -> '{Gen} v -> '{Gen} Map k v (+3 metadata)
 test.mapOf.doc       : Doc (+2 metadata)
 test.pairOf          : '{Gen} a -> '{Gen} b -> '{Gen} (a, b) (+3 metadata)
 test.pairOf.doc      : Doc (+2 metadata)

Name changes:

Original         Changes
 test.list        test.listOf (added)
                  test.list (removed)

 test.set         test.setOf (added)
                  test.set (removed)

 test.set.doc     test.setOf.doc (added)
                  test.set.doc (removed)

Add Char generators

Overview

This unison pull request aims to add Generators in the base.test.v1.Char namespace.

All functions have documentation linked, as well as author and license. In lieu of test cases, the documentation contains the exhausted source'd outputs of each generator

Code review

pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base:.prs.charGenerators

Added definitions:

 test.v1.gen.Char.alpha                     : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.alpha.doc                 : Doc
 test.v1.gen.Char.alpha.sampled             : [Char]
 test.v1.gen.Char.ascii                     : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.ascii.doc                 : Doc
 test.v1.gen.Char.ascii.sampled             : [Char]
 test.v1.gen.Char.asciiNonPrintable         : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.asciiNonPrintable.doc     : Doc
 test.v1.gen.Char.asciiNonPrintable.sampled : [Char]
 test.v1.gen.Char.asciiPrintable            : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.asciiPrintable.doc        : Doc
 test.v1.gen.Char.asciiPrintable.sampled    : [Char]
 test.v1.gen.Char.digit                     : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.digit.doc                 : Doc
 test.v1.gen.Char.digit.sampled             : [Char]
 test.v1.gen.Char.hexDigit                  : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.hexDigit.doc              : Doc (+1 metadata)
 test.v1.gen.Char.hexDigit.sampled          : [Char]
 test.v1.gen.Char.lower                     : '{Gen} Char (+3 metadata)
 test.v1.gen.Char.lower.doc                 : Doc
 test.v1.gen.Char.lower.sampled             : [Char]
 test.v1.gen.Char.upper                     : '{Gen} Char (+2 metadata)
 test.v1.gen.Char.upper.doc                 : Doc
 test.v1.gen.Char.upper.sampled             : [Char]

 patch test.v1.gen.Char.patch (added 14 updates)

Add Substitution ability and the contravariant functor for functions

Adds the ability to substitute one computation with another regardless of where you are in your current computation.

Inspired by the case study in chapter 7 of this paper.

This is basically an excuse to add callCC to unison.

Also includes the contravariant functor for a -> r while I was at it.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/bascott/codebase:.prs.base._add_substitution_ability

Added definitions:

 type Comp r a (+2 metadata)
 ability Substitution ref (+2 metadata)
 Comp.Comp                           : (โˆ€ e. a ->{e} r) -> Comp r a
 Substitution.jump                   : ref a -> a ->{Substitution ref} r (+3 metadata)
 Substitution.sub                    : {Substitution ref} (Either (ref a) a) (+3 metadata)
 Comp.<|                             : Comp r a -> a -> r (+2 metadata)
 Comp.contramap                      : (b -> a) -> Comp r a -> Comp r b (+2 metadata)
 Substitution.callCC                 : ((a ->{Substitution ref} b) ->{e} a)
                                     ->{e, Substitution ref} a (+3 metadata)
 Substitution.callCC.doc             : Doc (+2 metadata)
 Substitution.examples.ex1           : '{IO} () (+2 metadata)
 Substitution.jump.doc               : Doc (+2 metadata)
 Substitution.runComp                : '{e, Substitution (Comp r)} r ->{e} r (+2 metadata)
 Substitution.setjmp                 : a
                                     ->{Substitution ref} b
                                     ->{Substitution ref} r (+3 metadata)
 Substitution.setjmp.doc             : Doc (+2 metadata)
 Substitution.sub.doc                : Doc (+2 metadata)
 metadata.authors.bascott            : Author
 metadata.authors.bascott.guid       : GUID
 metadata.copyrightHolders.bascott   : CopyrightHolder
 metadata.licenses.bascott.bsd2_2020 : License
 metadata.licenses.bascott.bsd3_2020 : License
 metadata.licenses.bascott.mit_2020  : License

Add `Text.split` utility function to split texts on a single character.

A small function for a common operation on Texts.

Few Notes:

  • I've diffed against the latest release to get around the issues on trunk right now. If this function exists on trunk, let me know and I'll close the PR.
  • I did the author and license metadata after the fact and I'm not sure how best to verify that things are in order?

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.release._latest https://github.com/hojberg/unison-base:.prs._textSplit

Added definitions:

Text.split           : Char -> Text -> [Text] (+1 metadata)
Text.split.doc       : Doc
Text.split.tests.ex1 : [Result] (+1 metadata)
Text.split.tests.ex2 : [Result] (+1 metadata)

patch patch (added 1 updates)

Added `Stream.head` and `Stream.ignore` handlers

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base https://github.com/pchiusano/base

Updates:

 test.v1.Gen.toWeighted : '{Gen} a -> Weighted a
 โ†“
 test.v1.Gen.toWeighted : '{e, Gen} a ->{e} Weighted a

 test.v1.runs : Nat -> '{Gen} Test -> [Result]
 โ†“
 test.v1.runs : Nat -> '{e, Gen} Test ->{e} [Result]

 test.v1.sample : Nat -> '{Gen} a -> [a]
 โ†“
 test.v1.sample : Nat -> '{e, Gen} a ->{e} [a]

There were 2 auto-propagated updates.

Added definitions:

 Stream.head             : '{f, Stream e} a ->{f} Optional e (+2 metadata)
 Stream.head.handler     : Request {Stream e} a -> Optional e (+2 metadata)
 Stream.head.tests.ex1   : [Result] (+3 metadata)
 Stream.ignore           : '{f, Stream e} a ->{f} a (+2 metadata)
 Stream.ignore.handler   : Request {Stream e} a -> a (+2 metadata)
 Stream.ignore.tests.ex1 : [Result] (+3 metadata)
 force                   : '{e} a ->{e} a (+2 metadata)

 patch patch (added 3 updates)

Name changes:

Original                                      Changes
 test.internals.v1.Test.passedUnexpectedly โ”   test.v1.unexpectedOk (added)
 test.v1.unexpected.ok                     โ”˜   test.v1.unexpected.ok (removed)

 test.internals.v1.Test.provedUnexpectedly โ”   test.v1.unexpectedProven (added)
 test.v1.unexpected.proven                 โ”˜   test.v1.unexpected.proven (removed)

Observation is that whenever you write a convenience function like Stream.head : '{Stream e} a -> Optional a which just wraps a handler, it pays to generalize it to pass along other abilities: Stream.head : '{Stream e, other} a ->{other} Optional e.

Stream functions

DRAFT: docs and tests in progress

This PR adds a bunch of Stream functions (and a handful of Either functions that are used in the Stream function implementations). Design constraints include:

  • use general signatures
  • preserve result values whenever reasonable (useful for applications such as logged computations)
  • emit eagerly, although I didn't adhere to this constraint consistently, in some cases because the restriction on top-level definitions prevents it (e.g., Stream.Nat.all) and in others because it seemed like a delayed result would better suit the most likely use cases (e.g., Stream.cons)

Interesting/Controversial Decisions

I had a hard time deciding whether functions that ignore the return value of a streaming computation (e.g., Stream.toList) should be parameterized by the return type of that computation (i.e., should Stream.toList : '{g, Stream a} () ->{g} [a] or : '{g, Stream a} r ->{g} [a]?). On the one hand, using () makes it explicit that the function does not distinguish among return values of the stream, but on the other hand it's less flexible for users who are forced to pass void s rather than just s for a non-unit-valued stream s. Ultimately, I decided to favor flexibility.

Issues

The pull request shows a name conflict for Stream.toList, although the patch includes a term replacement entry.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/anovstrup/unisonweb-base:.prs._stream

New name conflicts:

 Stream.toList#fl0g3klg92 : '{e, Stream a} () ->{e} [a]
 โ†“
 โ”Œ Stream.toList#fl0g3klg92 : '{e, Stream a} () ->{e} [a]
 โ”” Stream.toList#hd25q36900 : '{g, Stream a} r ->{g} [a]
   +  anovstrup.mit_2020  : License
   +  unisoncomputing2020 : License
   +  pchiusano           : Author
   +  authors.anovstrup   : Author

Updates:

 patch patch (added 1 updates)

Added definitions:

 Either.fold                      : โˆ€ o ๐•– i1 i.
                                    (i1 ->{๐•–} o) -> (i ->{๐•–} o) -> Either i1 i ->{๐•–} o (+2 metadata)
 Either.left                      : Either l r -> Optional l (+2 metadata)
 Either.right                     : Either l r -> Optional r (+2 metadata)
 Either.unwrap                    : Either a a -> a (+2 metadata)
 โ”Œ Stream.++                      : (v1 ->{g, Stream a} v2)
                                  -> (v2 ->{g, Stream a} v3)
                                  -> v1
                                  ->{g, Stream a} v3 (+2 metadata)
 โ”” Stream.append                  : (v1 ->{g, Stream a} v2)
                                  -> (v2 ->{g, Stream a} v3)
                                  -> v1
                                  ->{g, Stream a} v3 (+2 metadata)
 โ”Œ Stream.+:                      : a -> '{Stream a} r -> '{Stream a} r (+2 metadata)
 โ”” Stream.cons                    : a -> '{Stream a} r -> '{Stream a} r (+2 metadata)
 Stream.Int.all                   : '{Stream Int} a (+2 metadata)
 Stream.Int.from                  : Int ->{Stream Int} a (+2 metadata)
 Stream.Int.negatives             : '{Stream Int} a (+2 metadata)
 Stream.Int.positives             : '{Stream Int} a (+2 metadata)
 Stream.Int.range                 : Int ->{Stream Int} Int ->{Stream Int} () (+2 metadata)
 Stream.Nat.all                   : '{Stream Nat} a (+2 metadata)
 โ”Œ Stream.Nat.from                : Nat ->{Stream Nat} a (+2 metadata)
 โ”” Stream.from                    : Nat ->{Stream Nat} a (+2 metadata)
 โ”Œ Stream.Nat.to                  : Nat ->{Stream Nat} () (+3 metadata)
 โ”” Stream.to                      : Nat ->{Stream Nat} () (+3 metadata)
 Stream.drop                      : Nat -> '{g, Stream a} r ->{g, Stream a} r (+2 metadata)
 Stream.drop.test                 : [Result] (+3 metadata)
 Stream.emitAndReturn             : a ->{Stream a} a (+2 metadata)
 Stream.filter                    : (a ->{g} Boolean)
                                  -> '{g, Stream a} r
                                  ->{g, Stream a} r (+2 metadata)
 Stream.filter.test               : [Result] (+3 metadata)
 Stream.flatMap                   : (a -> '{e, Stream a} r)
                                  -> '{e, Stream a} r
                                  ->{e, Stream a} r (+2 metadata)
 Stream.fold                      : (b ->{g} a ->{g} b)
                                  -> b
                                  -> '{g, Stream a} r
                                  ->{g} b (+2 metadata)
 Stream.fold.test                 : [Result] (+3 metadata)
 Stream.foldWithResult            : (b ->{g} a ->{g} b)
                                  -> b
                                  -> '{g, Stream a} r
                                  ->{g} (b, r) (+2 metadata)
 Stream.foldWithResult.handler    : (b ->{g} a ->{g} b)
                                  -> b
                                  -> Request (Stream a) r
                                  ->{g} (b, r) (+2 metadata)
 Stream.foldWithResult.test       : [Result] (+3 metadata)
 Stream.fromList                  : [a] ->{Stream a} () (+2 metadata)
 Stream.interleave                : '{Stream a} r -> '{Stream a} r ->{Stream a} r (+2 metadata)
 Stream.interleave.handler        : '{e} r
                                  -> Request (Stream a) r
                                  ->{e, Stream a} r (+2 metadata)
 Stream.map                       : (a ->{g} b)
                                  -> '{g, Stream a} r
                                  ->{g, Stream b} r (+2 metadata)
 Stream.map.test                  : [Result] (+3 metadata)
 Stream.pipe                      : '{g, Stream a} r1
                                  -> '{g, Stream b, Ask a} r2
                                  ->{g, Stream b} Either r1 r2 (+2 metadata)
 Stream.pipe'                     : '{g, Stream a} r
                                  -> '{g, Stream b, Ask a} r
                                  ->{g, Stream b} r (+2 metadata)
 Stream.pipe.handler              : '{g, Stream a} r1
                                  -> Request {Ask a, Stream b} r2
                                  ->{g, Stream b} Either r1 r2 (+2 metadata)
 Stream.scan                      : (b ->{g} a ->{g} b)
                                  -> b
                                  -> '{g, Stream a} r
                                  ->{g, Stream b} r (+2 metadata)
 Stream.take                      : Nat
                                  -> '{g, Stream a} r
                                  ->{g, Stream a} Optional r (+2 metadata)
 Stream.take.testCompletion       : [Result] (+3 metadata)
 Stream.take.testEarlyTermination : [Result] (+4 metadata)
 Stream.terminated                : '{g, Stream a} r ->{g, Stream (Optional a)} r (+2 metadata)
 Stream.terminated.test           : [Result] (+3 metadata)
 Stream.toList.test.bidirectional : [Result] (+3 metadata)
 Stream.toListWithResult          : '{g, Stream a} r ->{g} ([a], r) (+2 metadata)
 Stream.zip                       : '{Stream a} r1
                                  -> '{Stream b} r2
                                  ->{Stream (a, b)} Either r1 r2 (+2 metadata)

Name changes:

Original         Changes
 Stream.range     Stream.Nat.range (added)

Add `List.head`

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk.List https://github.com/runarorama/berlinfp

Added definitions:

 head                           : [a] -> Optional a (+1 metadata)
 head.doc                       : Doc
 head.examples.evaluated.elems  : Optional Nat
 head.examples.evaluated.empty  : Optional a
 head.examples.evaluated.single : Optional Nat
 head.test                      : [Result] (+1 metadata)

Add `scanl` and `scanr`

This adds scanr and scanl for List, and the corresponding functions for Nonempty. Includes pretty good tests and lots of examples.

Also added:

  • Boolean.and and Boolean.or as first-class functions.
  • Doc.example for constructing an example from a termRef.

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/runarorama/mybase:._topic.scan

Added definitions:

1.  Boolean.and                        : Boolean
                                       -> Boolean
                                       -> Boolean (+3 metadata)
2.  Boolean.and.doc                    : Doc (+2 metadata)
3.  Boolean.or                         : Boolean
                                       -> Boolean
                                       -> Boolean (+3 metadata)
4.  Boolean.or.doc                     : Doc (+2 metadata)
5.  Doc.example                        : Term -> Doc (+3 metadata)
6.  Doc.example.doc                    : Doc (+2 metadata)
7.  List.Nonempty.scanl                : (a ->{e} a ->{e} a)
                                       -> Nonempty a
                                       ->{e} Nonempty a (+3 metadata)
8.  List.Nonempty.scanl.doc            : Doc (+2 metadata)
9.  List.Nonempty.scanl.examples.asDoc : Doc (+2 metadata)
10. List.Nonempty.scanl.test           : [Test.Result] (+3 metadata)
11. List.Nonempty.scanr                : (a ->{e} a ->{e} a)
                                       -> Nonempty a
                                       ->{e} Nonempty a (+3 metadata)
12. List.Nonempty.scanr.doc            : Doc (+2 metadata)
13. List.Nonempty.scanr.examples.asDoc : Doc (+2 metadata)
14. List.Nonempty.scanr.test           : [Test.Result] (+3 metadata)
15. List.scanl                         : (b ->{e} a ->{e} b)
                                       -> b
                                       -> [a]
                                       ->{e} Nonempty b (+3 metadata)
16. List.scanl.doc                     : Doc (+2 metadata)
17. List.scanl.examples.asDoc          : Doc (+2 metadata)
18. List.scanl.examples.ex1            : Nonempty Nat (+2 metadata)
19. List.scanl.examples.ex2            : Nonempty Nat (+2 metadata)
20. List.scanl.examples.ex3            : Nonempty Nat (+2 metadata)
21. List.scanl.examples.ex4            : Nonempty Nat (+2 metadata)
22. List.scanl.examples.ex5            : Nonempty Nat (+2 metadata)
23. List.scanl.test                    : [Test.Result] (+3 metadata)
24. List.scanr                         : (a ->{e} b ->{e} b)
                                       -> b
                                       -> [a]
                                       ->{e} Nonempty b (+3 metadata)
25. List.scanr.doc                     : Doc (+2 metadata)
26. List.scanr.examples.asDoc          : Doc (+2 metadata)
27. List.scanr.examples.ex1            : Nonempty Nat (+2 metadata)
28. List.scanr.examples.ex2            : Nonempty Nat (+2 metadata)
29. List.scanr.examples.ex3            : Nonempty Nat (+2 metadata)
30. List.scanr.examples.ex4            : Nonempty Boolean (+2 metadata)
31. List.scanr.examples.ex5            : Nonempty Nat (+2 metadata)
32. List.scanr.test                    : [Test.Result] (+3 metadata)

Clean up the `test` namespace by putting generators in `gen`

This is a small change that only includes moving some names around for consistency and cleanup.

Code review

The changes summarized below are available for you to review, using the
following command:

pull-request.load https://github.com/unisonweb/base:.trunk.test https://github.com/runarorama/mybase:.genCleanup.test

Name changes:

Original        Changes
 boolean         gen.boolean (added)
                 boolean (removed)

 boolean.doc     gen.boolean.doc (added)
                 boolean.doc (removed)

 empty           gen.empty (added)
                 empty (removed)

 int             gen.int (added)
                 int (removed)

 listOf          gen.listOf (added)
                 listOf (removed)

 mapOf           gen.mapOf (added)
                 mapOf (removed)

 mapOf.doc       gen.mapOf.doc (added)
                 mapOf.doc (removed)

 nat             gen.nat (added)
                 nat (removed)

 natIn           gen.natIn (added)
                 natIn (removed)

 pairOf          gen.pairOf (added)
                 pairOf (removed)

 pairOf.doc      gen.pairOf.doc (added)
                 pairOf.doc (removed)

Add Void and absurd

Adding

type Void =

Void.doc = [: The uninhabited type.

No values of this type can be constructed, so it can be used for example 
to represent the return type of non-terminating computations. :]

absurd : Void -> a
absurd = cases

Umm, I temporarily hacked the parser in my ucm build to accept that empty 'cases' statement... Alternative would be to use bug as per this. I gave up trying to do a proper parser change to accept empty match/cases, and it'd be a very debatable change anyway.

Code review

The changes summarized below are available for you to review, using the following command:

    pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/atacratic/unison-playpen:._base.prs._1
  
  Added definitions:
  
     type Void (+3 metadata)
     Void.doc : Doc (+2 metadata)
     absurd   : Void -> a (+2 metadata)

(pr.create took several minutes...)

This PR is probably too small to be worth the overhead, for which apologies.

contributing guidelines don't acknowledge trunk or PR namespace

I think that CONTRIBUTING.md might be in need of updating. It doesn't seem to reflect that base now follows a trunk namespace convention. It also doesn't seem to follow the suggestions of making changes in a .pr._myFeature namespace.

This is an issue and not a PR because I'm not sure that I understand the proper way to do things yet. I've mucked things up a few times trying to figure out where I need to add :.prs._myFeature in the various push, pull, and pull-request.create commands.

add test.gen.optional

I haven't added a test based on this comment on the test.gen.either PR, but here is some example output:

> sample 5 (test.gen.optional nat)                                                                                                                                           
  โงฉ                                                                                                                                                                          
  [None, Some 0, Some 1, Some 2, Some 3]   

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load [email protected]:unisonweb/base:.trunk [email protected]:ceedubs/unison-dev:.prs.base._genOption

Added definitions:

 test.gen.optional     : '{Gen} a -> '{Gen} Optional a (+3 metadata)
 test.gen.optional.doc : Doc (+2 metadata)

base.Search.indexOf is misnamed should be anyIndexOf

indexOf is expected to find the first index on the given value while unison provides the index of the first value encountered in a binary search :

 test> tests.http.utils.indexof.happy = run (expect ((base.Search.indexOf 1 [1,1]) == Some 0))
   
  :no_entry_sign: FAILED

In Haskell:

   Data.List.elemIndex 1 [1,1]
=> Just 0

Suggestion would be to change the function name to anyIndexOf and adding a simple indexOf function to List

Add docs to `Tuple`

This PR adds some documentation to Tuple, Tuple.at1, Tuple.at2, Tuple.at3, and Tuple.at4 as well as tests supporting the documentation.

Tuple.doc briefly explains the syntax sugar with tuples.


The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/emiflake/unison-emi.git:.prs.base._tuple_docs

Updates:

 type Tuple a b
   +  Tuple.doc : Doc

 Tuple.at1 : Tuple a b -> a
 +  at1.doc : Doc

 Tuple.at2 : Tuple a (Tuple b c) -> b
 +  at2.doc : Doc

 Tuple.at3 : Tuple a (Tuple b (Tuple c d)) -> c
 +  at3.doc : Doc

 Tuple.at4 : Tuple a (Tuple b (Tuple c (Tuple d e))) -> d
 +  at4.doc : Doc

 patch patch (added 1 updates)

Added definitions:

 Tuple.at1.doc       : Doc (+2 metadata)
 Tuple.at1.tests.ex1 : [Result] (+3 metadata)
 Tuple.at2.doc       : Doc (+2 metadata)
 Tuple.at2.tests.ex1 : [Result] (+3 metadata)
 Tuple.at3.doc       : Doc (+2 metadata)
 Tuple.at3.tests.ex1 : [Result] (+3 metadata)
 Tuple.at3.tests.ex2 : [Result] (+3 metadata)
 Tuple.at4.doc       : Doc (+2 metadata)
 Tuple.at4.tests.ex1 : [Result] (+3 metadata)
 Tuple.at4.tests.ex2 : [Result] (+3 metadata)
 Tuple.doc           : Doc (+2 metadata)
 Tuple.tests.ex1     : [Result] (+2 metadata)
 Tuple.tests.ex2     : [Result] (+3 metadata)

Add base.List.last

This issue aims to add the List.last function to the unison base library.

  • Quick wrapper around List.at (List.size drop 1)
  • Example inputs added
  • Evaluated outputs added
  • Unit tests added
  • Documentation added and linked

It's the first time I am following this process so I am not 100% sure which parts of the following you might need:

.petets.base> pull-request.create https://github.com/unisonweb/base https://github.com/pete-ts/base
โš™  git clone --quiet --depth 1 'https://github.com/unisonweb/base' /home/petet/.cache/unisonlanguage/gitfiles/q0rume4r1p1lc5tut0gcbbcvndjgr8ai0qst6ej9bdjr1vcgmtueo0103oi4kt4tr0m1vok5sbkk91g1qcr2og9pit3rp8ceeq752r8/HEAD
โš™  git -C /home/petet/.cache/unisonlanguage/gitfiles/q0rume4r1p1lc5tut0gcbbcvndjgr8ai0qst6ej9bdjr1vcgmtueo0103oi4kt4tr0m1vok5sbkk91g1qcr2og9pit3rp8ceeq752r8/HEAD rev-parse --git-dir
.git
โš™  git clone --quiet --depth 1 'https://github.com/pete-ts/base' /home/petet/.cache/unisonlanguage/gitfiles/cut54dgrge7sdifko04ntkptm7jl3jqlc3f9e07cd3vomjqem7g5ij0f8uij8l8f8gjrtjbcjnndj21a80ipdsolgv85cdd9iv06j58/HEAD
โš™  git -C /home/petet/.cache/unisonlanguage/gitfiles/cut54dgrge7sdifko04ntkptm7jl3jqlc3f9e07cd3vomjqem7g5ij0f8uij8l8f8gjrtjbcjnndj21a80ipdsolgv85cdd9iv06j58/HEAD rev-parse --git-dir
.git

  The changes summarized below are available for you to review, using the following
  command:
  
    pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base
  
  Added definitions:
  
     List.last                           : [a] -> Optional a (+1 metadata)
     List.last.doc                       : Doc
     List.last.examples.elems            : [Nat]
     List.last.examples.empty            : [elem]
     List.last.examples.evaluated.elems  : Optional Nat
     List.last.examples.evaluated.empty  : Optional a
     List.last.examples.evaluated.single : Optional Nat
     List.last.examples.single           : [Nat]
     List.last.tests.elems               : [Result]
     List.last.tests.empty               : [Result]
     List.last.tests.single              : [Result]

Adds List.filter

Overview

This PR adds the List.filter function, along with:

  • documentation
  • a small number of unit tests
  • author and license links

Code review

pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base:.prs.listFilter

Added definitions:

 List.filter                : (a ->{๐•–} Boolean) -> [a] ->{๐•–} [a] (+3 metadata)
 List.filter.doc            : Doc
 List.filter.tests.empty    : [Result] (+1 metadata)
 List.filter.tests.negative : [Result] (+1 metadata)
 List.filter.tests.positive : [Result] (+1 metadata)

 patch List.patch (added 1 updates)

Exponential behaviour in `Test.both`

Given

test.laws.lattice : '{Gen} a -> (a ->{e} a ->{e} a) -> (a ->{e} a ->{e} a) ->{Gen,e} Test
test.laws.lattice gen meet join = 
  absorption gen meet join 
    `both` associative gen meet
    `both` associative gen join
    `both` commutative gen meet
    `both` commutative gen join

The following test essentially never completes:

test> minMaxLattice = runs 2 '(test.laws.lattice nat Nat.min Nat.max)

Testing helper to print debug output on failure.

Overview

Adds a === operator/test helper to wrap around Universal.== and on false uses "bug" to show the two values being compared. ("Debug output if my test is failing").

The main reason I am adding this is the fact that I have found myself needing/using it quite frequently. I do not have an opinion/preference on the naming convention (my mind is currently wired on scala.specs2 must_=== probably), just leaving it here to start a discussion. check/check' take an input of Boolean so a wrapper around those that takes (a -> a -> Boolean) should also be trivial, to have a comparable debug wrapper around check/check' too.

  • "No point in unit testing": a failure explodes ucm and cannot be added.
  • So this behaviour is captured fully in the .doc.
  • Linked to doc/author/license.

Code review

The changes summarized below are available for you to review, using the following
command:

pull-request.load https://github.com/unisonweb/base https://github.com/pete-ts/base:.prs.tripleEquals

Added definitions:

 โ”Œ test.internals.v1.Test.===           : a -> a -> Boolean (+3 metadata)
 โ”” test.internals.v1.Test.equalsOrBug   : a -> a -> Boolean (+3 metadata)
 test.internals.v1.Test.equalsOrBug.doc : Doc

 patch test.internals.v1.Test.patch (added 1 updates)

Add .ascii namespace with various predicates and utilities.

This adds an ascii namespace with your usual isUpper, isDigit, toLower etc. stuff that every language has.

Due to performance issues, I had to use git directly to actually push this to my fork, so hopefully it still came out ok. Let me know if I've missed anything.

Code review

  The changes summarized below are available for you to review, using the following command:
  
    pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/zenhack/base-1:.prs.base._ascii
  
  Added definitions:
  
     ascii._priv.inRange            : Char -> Char -> Char -> Boolean (+1 metadata)
     ascii._priv.inRange.doc        : Doc
     ascii._priv.lowerUpperDiff     : Int (+1 metadata)
     ascii._priv.lowerUpperDiff.doc : Doc
     ascii.doc                      : Doc
     ascii.isAlphaNum               : Char -> Boolean (+1 metadata)
     ascii.isAlphaNum.doc           : Doc
     ascii.isAscii                  : Char -> Boolean (+1 metadata)
     ascii.isAscii.doc              : Doc
     ascii.isBlank                  : Char -> Boolean (+1 metadata)
     ascii.isBlank.doc              : Doc
     ascii.isControl                : Char -> Boolean (+1 metadata)
     ascii.isControl.doc            : Doc
     ascii.isDigit                  : Char -> Boolean (+1 metadata)
     ascii.isDigit.doc              : Doc
     ascii.isGraph                  : Char -> Boolean (+1 metadata)
     ascii.isGraph.doc              : Doc
     ascii.isHexDigit               : Char -> Boolean (+1 metadata)
     ascii.isHexDigit.doc           : Doc
     ascii.isLetter                 : Char -> Boolean (+1 metadata)
     ascii.isLetter.doc             : Doc
     ascii.isLower                  : Char -> Boolean (+1 metadata)
     ascii.isLower.doc              : Doc
     ascii.isPrint                  : Char -> Boolean (+1 metadata)
     ascii.isPrint.doc              : Doc
     ascii.isPunct                  : Char -> Boolean (+1 metadata)
     ascii.isPunct.doc              : Doc
     ascii.isSpace                  : Char -> Boolean (+1 metadata)
     ascii.isSpace.doc              : Doc
     ascii.isUpper                  : Char -> Boolean (+1 metadata)
     ascii.isUpper.doc              : Doc
     ascii.tests.propUpperLower     : [Result] (+2 metadata)
     ascii.tests.propUpperLower.doc : Doc
     ascii.tests.toLower            : [Result] (+1 metadata)
     ascii.tests.toUpper            : [Result] (+1 metadata)
     ascii.toLower                  : Char -> Char (+1 metadata)
     ascii.toLower.doc              : Doc
     ascii.toUpper                  : Char -> Char (+1 metadata)
     ascii.toUpper.doc              : Doc
  
     patch ascii._priv.patch (added 1 updates)
     patch ascii.patch (added 2 updates)

Memo ability

This PR adds a Memo ability for memoization:

ability Memo e a where memoize : '{e, Memo e a} a ->{Memo e a} a

Memo.evalOnce : '{e, Memo {e} a} b ->{e} b
...

Memo.evalOnce.handler :
    Map ('{e, Memo {e} a} a) a -> 
    Request (Memo {e} a) b ->{e} 
    (b, Map ('{e, Memo {e} a} a) a)
...

Memo.memoize.examples.memoFib : Nat ->{Memo {} Nat} Nat
Memo.memoize.examples.memoFib n = memoize 'let
  if n == 0 then 1
  else if n == 1 then 1
  else memoFib (drop n 2) + memoFib (drop n 1))

-- `evalOnce` makes `memoFib` efficient
> Memo.evalOnce '(Memo.memoize.examples.memoFib 50)
  โงฉ
  20365011074

The PR includes a test demonstrating that Memo.evalOnce really does evaluate each memoized subcomputation only once. (Evaluating the memoFib example also demonstrates this, as an unmemoized recursive implementation has exponential running time.)

I also considered an Eval ability that might also be useful. Whereas Memo leaves it up to the handler to determine what kind of memoization to provide (e.g., permanent storage vs. temporary caching), Eval would provide separate operations to offer more control at the call site:

ability Eval where 
  always: 'a -> a
  cached: 'a -> a
  once: 'a -> a

Note: the code in this PR uses some of the definitions in PR #22.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:.trunk https://github.com/anovstrup/unisonweb-base:.prs._memo2

Added definitions:

 ability Memo e a (+2 metadata)
 Memo.memoize                  : '{e, Memo e a} a ->{Memo e a} a
 Memo.evalOnce                 : '{e, Memo {e} a} b ->{e} b (+3 metadata)
 Memo.evalOnce.doc             : Doc (+2 metadata)
 Memo.evalOnce.handler         : Map '{e, Memo {e} a} a a
                               -> Request (Memo {e} a) b
                               ->{e} (b, Map '{e, Memo {e} a} a a) (+2 metadata)
 Memo.evalOnce.test            : [Result] (+4 metadata)
 Memo.memoize.examples.memoFib : Nat ->{Memo {} Nat} Nat (+2 metadata)

Name changes:

Original             Changes
 Function.flatMap     bind (added)

use consistent spelling of licenses for ceedubs2020

Since I have lived in the US my whole life, I can't really explain why I spelled it licences instead of licenses for myself. This changes the name to be consistent with all of the other license metadata.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load [email protected]:unisonweb/base:.trunk [email protected]:ceedubs/unison-dev:.prs.base._americanLicense

Name changes:

Original                          Changes
 metadata.licences.ceedubs2020     metadata.licenses.ceedubs2020 (added)
                                   metadata.licences.ceedubs2020 (removed)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.