1
1
mirror of https://github.com/github/semantic.git synced 2024-12-25 07:55:12 +03:00

Merge branch 'master' into output-typeclass

This commit is contained in:
Rob Rix 2017-07-31 11:05:04 -04:00 committed by GitHub
commit e53adbd247
4 changed files with 0 additions and 316 deletions

View File

@ -79,9 +79,6 @@ library
, Syntax
, Term
, TreeSitter
, FDoc.Term
, FDoc.RecursionSchemes
, FDoc.NatExample
build-depends: base >= 4.8 && < 5
, aeson
, ansi-terminal

View File

@ -1,60 +0,0 @@
module FDoc.NatExample where
import Prologue
import Data.Functor.Foldable
-- Our base Functor. The recursive bit is parameterized by r.
data NatF r =
ZeroF
| SuccF r
deriving (Show, Functor)
-- Fix represents the "fixed point" for the NatF Functor, and enables recursion.
-- Important to note this has kind * -> *.
type Nat = Fix NatF
-- This is a fully applied type (Has kind *).
zero' :: Nat
zero' = Fix ZeroF
-- This is a partially applied type (has kind * -> *). The recursive bit is used
-- by recursion schemes and is referred to as the "carrier" functor.
succ' :: Nat -> Nat
succ' = Fix . SuccF
-- Catamorphism: "tear down" a recursive structure in the shape of Nat.
natToIntCata :: Nat -> Int
natToIntCata nats = cata algebra nats
where
algebra term = case term of
ZeroF -> 0
SuccF value -> 1 + value
-- Anamorphism: "build up" a recursive structure in the shape of Nat.
intToNatAna :: Int -> Nat
intToNatAna num = ana coalgebra num
where
coalgebra num = case num of
0 -> ZeroF
_ -> SuccF (num - 1)
-- Hylomorphism: first apply an anamorphism and then a catamorphism in the shape
-- of Nat.
natHylo :: Int -> Int
natHylo num = hylo algebra coalgebra num
where
algebra term = case term of
ZeroF -> 0
SuccF value -> 1 + value
coalgebra num = case num of
0 -> ZeroF
_ -> SuccF (num - 1)
-- Paramorphism: primitive recursion maintaining the original value along with
-- its computed value.
natPara :: Nat -> Int
natPara nats = para algebra nats
where
algebra value = case value of
ZeroF -> 0
(SuccF (_, value')) -> 1 + value'

View File

@ -1,186 +0,0 @@
{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies, TypeOperators #-}
module FDoc.RecursionSchemes where
import Data.Range
import Data.Record
import Category
import Term
import Syntax
import Prologue
import Prelude
import FDoc.Term
data NewField = NewField deriving (Show)
{-
Anamorphism -- add a new field to each term's Record fields
ana :: (a -> Base t a) -- a (Base t)-coalgebra
-> a -- seed
-> t -- resulting fixed point
Anamorphism as a recursion scheme "builds up" a recursive structure.
Anamorphisms work by using a coalgebra, which maps a seed value to a fixed point
structure.
The example below adds a new field to the `Record` fields.
-}
indexedTermAna :: [Text] -> Term Syntax (Record '[NewField, Range, Category])
indexedTermAna childrenLeaves = ana coalgebra (indexedTerm childrenLeaves)
where
coalgebra term = (NewField :. (extract term)) :< unwrap term
{-
Catamorphism example -- add a new field to each term's Record fields
cata :: (Base t a -> a) -- a (Base t)-algebra
-> t -- fixed point
-> a -- result
Catamorphism as a recursion scheme "tears down" a recursive structure.
Catamorphisms work by using an algebra, which maps a shape in our fixed point
structure to a new shape.
The example below adds a new field to the `Record` fields.
-}
indexedTermCata :: [Text] -> Term Syntax (Record '[NewField, Range, Category])
indexedTermCata childrenLeaves = cata algebra (indexedTerm childrenLeaves)
where
algebra :: Functor f => CofreeF f (Record t) (Cofree f (Record (NewField : t))) -> Cofree f (Record (NewField : t))
algebra term = cofree $ (NewField :. headF term) :< tailF term
{-
Anamorphism -- construct a Term from a string
The example below shows how to build up a recursive Term structure from a string
representation.
Example usage:
stringToTermAna "indexed" =>
CofreeT (Identity ( (Range {start = 1, end = 10} :. MethodCall :. Nil)
:<
Indexed
[ CofreeT (Identity ( (Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf1" ) )
, CofreeT (Identity ( (Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf2" ) )
, CofreeT (Identity ( (Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf3" ) )
] ))
First step is to match against the "indexed" string and begin building up a Cofree Indexed structure:
CofreeT (Identity ( (Range 1 10 :. Category.MethodCall :. Nil) :< Indexed ["leaf1", "leaf2", "leaf3"] ) )
While building up the `Indexed` structure, we continue to recurse over the
`Indexed` terms ["leaf1", "leaf2", "leaf3"]. These are pattern matched using
the catch all `_` and default to `Leaf` Syntax shapes:
CofreeT (Identity ( (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf "leaf1" ) )
CofreeT (Identity ( (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf "leaf2" ) )
CofreeT (Identity ( (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf "leaf3" ) )
These structures are substituted in place of ["leaf1", "leaf2", "leaf3"] in
the new cofree `Indexed` structure, resulting in a expansion of all possible
string terms.
-}
stringToTermAna :: Text -> Term Syntax (Record '[Range, Category])
stringToTermAna = ana coalgebra
where
coalgebra representation = case representation of
"indexed" -> (Range 1 10 :. Category.MethodCall :. Nil) :< Indexed ["leaf1", "leaf2", "leaf3"]
_ -> (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf representation
{-
Catamorphism -- construct a list of Strings from a recursive Term structure.
The example below shows how to tear down a recursive Term structure into a list
of String representation.
-}
termToStringCata :: Term Syntax (Record '[Range, Category]) -> [Text]
termToStringCata = cata algebra
where
algebra term = case term of
(_ :< Leaf value) -> [value]
(_ :< Indexed values) -> ["indexed"] <> Prologue.concat values
_ -> ["unknown"]
{-
Hylomorphism -- An anamorphism followed by a catamorphism
hylo :: Functor f => (f b -> b) -- an algebra
-> (a -> f a) -- a coalgebra
-> a -- seed value
-> b -- result
Hylomorphisms work by first applying a coalgebra (anamorphism) to build up a
structure. An algebra (catamorphism) is then applied to this structure. Because
of fusion the anamorphism and catamorphism occur in a single pass rather than
two separate traversals.
The example below shows how our algebra and coalgebra defined in the
termToStringCata and stringToTermAna can be utilized as a hylomorphism.
Example Usage:
stringTermHylo "indexed" => ["indexed", "leaf1", "leaf2", "leaf3"]
-}
stringTermHylo :: Text -> [Text]
stringTermHylo = hylo algebra coalgebra
where
algebra term = case term of
(_ :< Leaf value) -> [value]
(_ :< Indexed values) -> ["indexed"] <> Prologue.concat values
_ -> ["unknown"]
coalgebra stringRepresentation = case stringRepresentation of
"indexed" -> (Range 1 10 :. Category.MethodCall :. Nil) :< Indexed ["leaf1", "leaf2", "leaf3"]
_ -> (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf stringRepresentation
{-
Paramorphism -- primitive recursion that maintains a reference to the original value and its computed value.
para :: (Base t (t, a) -> a) -- an algebra that takes a tuple of the last input
-> t -- fixed point
-> a -- result
Paramorphisms, like all recursion schemes, work via a bottom up traversal
(leaves to root), in which an algebra is applied to every node in the recursive
structure. The difference between paramorphisms and catamorphisms is the algebra
receives a tuple of the original subobject and its computed value (t, a) where
`t` is the original suboject and `a` is the computed value.
The example implementation below calculates a string representation for each
Syntax type, flattening the recursive structure into a one dimensional list to
tuples. The tuple contains the original syntax subobject, and its computed
string representation. This example aims to showcase how paramorphisms work by
returning a final list of tuples that mimics the intermediate tuple shapes the
algebra receives throughout the bottom up traversal.
Example Usage:
let terms = indexedTerm ["leaf1", "leaf2", "leaf3"]
termPara terms = Recurse over the structure to start at the leaves (bottom up traversal):
tuple3 = ( CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf3")), "leaf3" ) : []
Continue the traversal from leaves to root:
tuple2:3 = ( CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf2")), "leaf2") : tuple3
tuple1:2:3 = ( CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf1" )), "leaf1") : tuple2:3
Compute the root:
tupleIndexed:1:2:3 = ( CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Indexed [])), "indexed" ) : tuple1:2:3
Final shape:
[ (CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Indexed [])) , "indexed")
, (CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf1")), "leaf1")
, (CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf2")), "leaf2")
, (CofreeT (Identity ((Range {start = 1, end = 10} :. MethodCall :. Nil) :< Leaf "leaf3")), "leaf3")
]
-}
termPara :: Term Syntax (Record '[Range, Category]) -> [(Term Syntax (Record '[Range, Category]), Text)]
termPara = para algebra
where
algebra term = case term of
(annotation :< Leaf representation) -> [(cofree (annotation :< Leaf representation), representation)]
(annotation :< Indexed values) -> [(cofree (annotation :< Indexed []), "indexed")] <> (values >>= Prelude.snd)
_ -> [(cofree ((Range 1 10 :. Category.MethodCall :. Nil) :< Leaf "unknown"), "unknown")]

View File

@ -1,67 +0,0 @@
{-# LANGUAGE DataKinds, TypeOperators #-}
module FDoc.Term where
import Data.Range
import Data.Record
import Category
import Term
import Syntax
import Prologue
{-
Constructs a Syntax.Leaf using the polymorphic type variable `leaf`.
This is in the TermF shape: CofreeF f a b where
f is the functor (Syntax.Leaf `leaf`)
a is the annotation (Record '[Range, Category])
b is the same type of functor defined by f
Two common convenience operations when working with CofreeF (for docs, see
Control.Comonad.Trans.Cofree.Types.CofreeF) are `headF` and `tailF`. `headF`
return the annotation portion of the CofreeF structure, and `tailF` returns the
functor portion (Syntax).
Example (from GHCi):
> let leaf = leafTermF "example"
> headF leaf
> Range {start = 1, end = 10} :. MethodCall :. Nil
> tailF leaf
> Leaf "example"
-}
leafTermF :: Text -> TermF Syntax (Record '[Range, Category]) b
leafTermF leaf = (Range 1 10 :. Category.MethodCall :. Nil) :< Leaf leaf
{-
Constructs a Syntax.Leaf using the polymorphic type variable `leaf`.
This is in the Term shape: Cofree f a where
f is the functor (Syntax.Leaf `leaf`)
a is the annotation (Record '[Range, Category])
Two common convenience operations when working with Cofree (for docs, see
Control.Comonad.Trans.Cofree.Types.Cofree) are `extract` and `unwrap`. `extract`
returns the annotation portion of the Cofree structure, and `unwrap` returns the
functor portion (Syntax).
Example (from GHCi):
> let leaf = leafTerm "example"
> extract leaf
> Range {start = 1, end = 10} :. MethodCall :. Nil
> unwrap leaf
> Leaf "example"
-}
leafTerm :: Text -> Cofree Syntax (Record '[Range, Category])
leafTerm = cofree . leafTermF
indexedTermF :: [Text] -> TermF Syntax (Record '[Range, Category]) (Term Syntax (Record '[Range, Category]))
indexedTermF leaves = (Range 1 10 :. Category.MethodCall :. Nil) :< Indexed (leafTerm <$> leaves)
indexedTerm :: [Text] -> Term Syntax (Record '[Range, Category])
indexedTerm leaves = cofree $ indexedTermF leaves