1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 14:21:31 +03:00

Merge branch 'master' into subclassing

This commit is contained in:
Patrick Thomson 2018-03-22 12:37:49 -04:00 committed by GitHub
commit ba67556ce6
3 changed files with 42 additions and 11 deletions

View File

@ -72,6 +72,7 @@ library
, Data.Patch , Data.Patch
, Data.Range , Data.Range
, Data.Record , Data.Record
, Data.Semigroup.App
, Data.Source , Data.Source
, Data.Span , Data.Span
, Data.SplitDiff , Data.SplitDiff

View File

@ -16,6 +16,7 @@ import Data.Abstract.Value
import Data.Functor.Classes import Data.Functor.Classes
import Data.Proxy import Data.Proxy
import Data.Semigroup.Foldable import Data.Semigroup.Foldable
import Data.Semigroup.App
import Data.Term import Data.Term
import Prelude hiding (fail) import Prelude hiding (fail)
import Prologue import Prologue
@ -51,14 +52,4 @@ instance Evaluatable s => Evaluatable (TermF s a) where
-- 3. Only the last statements return value is returned. -- 3. Only the last statements return value is returned.
instance Evaluatable [] where instance Evaluatable [] where
-- 'nonEmpty' and 'foldMap1' enable us to return the last statements result instead of 'unit' for non-empty lists. -- 'nonEmpty' and 'foldMap1' enable us to return the last statements result instead of 'unit' for non-empty lists.
eval = maybe unit (runImperative . foldMap1 (Imperative . subtermValue)) . nonEmpty eval = maybe unit (runApp . foldMap1 (App . subtermValue)) . nonEmpty
-- | A 'Semigroup' providing an imperative context which extends the local environment with new bindings.
newtype Imperative m a = Imperative { runImperative :: m a }
instance MonadEnvironment value m => Semigroup (Imperative m a) where
Imperative a <> Imperative b = Imperative (a *> b)
instance (MonadEnvironment value m, MonadValue value m) => Monoid (Imperative m value) where
mempty = Imperative unit
mappend = (<>)

39
src/Data/Semigroup/App.hs Normal file
View File

@ -0,0 +1,39 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Semigroup.App
( App(..)
, AppMerge(..)
) where
import Control.Applicative
import Data.Semigroup
-- $setup
-- >>> import Test.QuickCheck
-- >>> instance Arbitrary (f a) => Arbitrary (App f a) where arbitrary = App <$> arbitrary ; shrink = map App . shrink . runApp
-- >>> instance Arbitrary (f a) => Arbitrary (AppMerge f a) where arbitrary = AppMerge <$> arbitrary ; shrink = map AppMerge . shrink . runAppMerge
-- | 'Semigroup' under '*>'.
newtype App f a = App { runApp :: f a }
deriving (Alternative, Applicative, Bounded, Enum, Eq, Foldable, Functor, Monad, Ord, Show, Traversable)
-- $ Associativity:
-- prop> \ a b c -> a <> (b <> c) == (a <> b) <> (c :: App Maybe Integer)
instance Applicative f => Semigroup (App f a) where
App a <> App b = App (a *> b)
-- | 'Semigroup' and 'Monoid' under '<*>' and '<>'.
newtype AppMerge f a = AppMerge { runAppMerge :: f a }
deriving (Alternative, Applicative, Bounded, Enum, Eq, Foldable, Functor, Monad, Ord, Show, Traversable)
-- $ Associativity:
-- prop> \ a b c -> a <> (b <> c) == (a <> b) <> (c :: AppMerge Maybe String)
instance (Applicative f, Semigroup a) => Semigroup (AppMerge f a) where
AppMerge a <> AppMerge b = AppMerge ((<>) <$> a <*> b)
-- $ Identity:
-- prop> \ a -> mempty <> a == (a :: AppMerge Maybe String)
-- prop> \ a -> a <> mempty == (a :: AppMerge Maybe String)
instance (Applicative f, Monoid a, Semigroup a) => Monoid (AppMerge f a) where
mempty = AppMerge (pure mempty)
mappend = (<>)