-
Notifications
You must be signed in to change notification settings - Fork 271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create some unit tests for Doc syntax #5376
Changes from all commits
b422a7d
1dcc332
30a49f6
b57428f
05cc1c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,4 +69,5 @@ library | |
, unison-core | ||
, unison-hash | ||
, unison-prelude | ||
, unison-util-recursion | ||
default-language: GHC2021 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,4 +64,5 @@ library | |
, text | ||
, unison-hash | ||
, unison-prelude | ||
, unison-util-recursion | ||
default-language: Haskell2010 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
name: unison-util-recursion | ||
github: unisonweb/unison | ||
copyright: Copyright (C) 2013-2022 Unison Computing, PBC and contributors | ||
|
||
ghc-options: -Wall | ||
|
||
dependencies: | ||
- base | ||
- free | ||
|
||
library: | ||
source-dirs: src | ||
when: | ||
- condition: false | ||
other-modules: Paths_unison_util_recursion | ||
|
||
default-extensions: | ||
- ApplicativeDo | ||
- BangPatterns | ||
- BlockArguments | ||
- DeriveAnyClass | ||
- DeriveFoldable | ||
- DeriveFunctor | ||
- DeriveGeneric | ||
- DeriveTraversable | ||
- DerivingStrategies | ||
- DerivingVia | ||
- DoAndIfThenElse | ||
- DuplicateRecordFields | ||
- FlexibleContexts | ||
- FlexibleInstances | ||
- FunctionalDependencies | ||
- GeneralizedNewtypeDeriving | ||
- ImportQualifiedPost | ||
- LambdaCase | ||
- MultiParamTypeClasses | ||
- NamedFieldPuns | ||
- OverloadedStrings | ||
- PatternSynonyms | ||
- RankNTypes | ||
- ScopedTypeVariables | ||
- StandaloneDeriving | ||
- TupleSections | ||
- TypeApplications | ||
- TypeFamilies | ||
- ViewPatterns |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{-# LANGUAGE DefaultSignatures #-} | ||
{-# LANGUAGE QuantifiedConstraints #-} | ||
{-# LANGUAGE UndecidableInstances #-} | ||
|
||
module Unison.Util.Recursion | ||
( Algebra, | ||
Recursive (..), | ||
cataM, | ||
para, | ||
Fix (..), | ||
Cofree' (..), | ||
) | ||
where | ||
|
||
import Control.Arrow ((&&&)) | ||
import Control.Comonad.Cofree (Cofree ((:<))) | ||
import Control.Monad ((<=<)) | ||
|
||
type Algebra f a = f a -> a | ||
|
||
class Recursive t f | t -> f where | ||
cata :: (Algebra f a) -> t -> a | ||
default cata :: (Functor f) => (f a -> a) -> t -> a | ||
cata φ = φ . fmap (cata φ) . project | ||
project :: t -> f t | ||
default project :: (Functor f) => t -> f t | ||
project = cata (fmap embed) | ||
embed :: f t -> t | ||
{-# MINIMAL embed, (cata | project) #-} | ||
|
||
cataM :: (Recursive t f, Traversable f, Monad m) => (f a -> m a) -> t -> m a | ||
cataM φ = cata $ φ <=< sequenceA | ||
|
||
para :: (Recursive t f, Functor f) => (f (t, a) -> a) -> t -> a | ||
para φ = snd . cata (embed . fmap fst &&& φ) | ||
|
||
newtype Fix f = Fix (f (Fix f)) | ||
|
||
deriving instance (forall a. (Show a) => Show (f a)) => Show (Fix f) | ||
|
||
deriving instance (forall a. (Eq a) => Eq (f a)) => Eq (Fix f) | ||
|
||
deriving instance (Eq (Fix f), forall a. (Ord a) => Ord (f a)) => Ord (Fix f) | ||
|
||
instance (Functor f) => Recursive (Fix f) f where | ||
embed = Fix | ||
project (Fix f) = f | ||
|
||
data Cofree' f a x = a :<< f x | ||
deriving (Foldable, Functor, Traversable) | ||
Comment on lines
+49
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious, any reason why not use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should have. I think I got confused and tried to use the isomorphic In my own code, I don’t use those because they’re not strict in the functor parameter, so they don’t result in lawful fixed points. But my |
||
|
||
-- | | ||
-- | ||
-- __NB__: `Cofree` from “free” is lazy, so this instance is technically partial. | ||
instance (Functor f) => Recursive (Cofree f a) (Cofree' f a) where | ||
embed (a :<< fco) = a :< fco | ||
project (a :< fco) = a :<< fco |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
cabal-version: 1.12 | ||
|
||
-- This file has been generated from package.yaml by hpack version 0.36.0. | ||
-- | ||
-- see: https://github.com/sol/hpack | ||
|
||
name: unison-util-recursion | ||
version: 0.0.0 | ||
homepage: https://github.com/unisonweb/unison#readme | ||
bug-reports: https://github.com/unisonweb/unison/issues | ||
copyright: Copyright (C) 2013-2022 Unison Computing, PBC and contributors | ||
build-type: Simple | ||
|
||
source-repository head | ||
type: git | ||
location: https://github.com/unisonweb/unison | ||
|
||
library | ||
exposed-modules: | ||
Unison.Util.Recursion | ||
hs-source-dirs: | ||
src | ||
default-extensions: | ||
ApplicativeDo | ||
BangPatterns | ||
BlockArguments | ||
DeriveAnyClass | ||
DeriveFoldable | ||
DeriveFunctor | ||
DeriveGeneric | ||
DeriveTraversable | ||
DerivingStrategies | ||
DerivingVia | ||
DoAndIfThenElse | ||
DuplicateRecordFields | ||
FlexibleContexts | ||
FlexibleInstances | ||
FunctionalDependencies | ||
GeneralizedNewtypeDeriving | ||
ImportQualifiedPost | ||
LambdaCase | ||
MultiParamTypeClasses | ||
NamedFieldPuns | ||
OverloadedStrings | ||
PatternSynonyms | ||
RankNTypes | ||
ScopedTypeVariables | ||
StandaloneDeriving | ||
TupleSections | ||
TypeApplications | ||
TypeFamilies | ||
ViewPatterns | ||
ghc-options: -Wall | ||
build-depends: | ||
base | ||
, free | ||
default-language: Haskell2010 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious why not use
recursion-schemes
directly?I personally find your encoding here less confusing than all the
Base
type-family nonsense, but it's also nice to maintain compatibility with the ecosystem where possible 😄There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, my plan was to replace this with a recursion scheme library eventually. At this point, I was just trying to centralize the (mostly) existing copies of this pattern.
I’m happy to put in recursion-schemes, but I also have my own recursion scheme library, Yaya, which makes some different decisions than recursion-schemes1. One of them is the use of
FunctionalDependencies
, as you pointed out. Another is that Yaya tries to provide totality (especially when paired withNoRecursion
).So I just punted on that discussion for now.
Footnotes
There’s a more in-depth comparison with recursion-schemes in Yaya’s README. ↩