Skip to content

Instantly share code, notes, and snippets.

@Cedev
Created July 19, 2017 01:28
Show Gist options
  • Save Cedev/c9f3769eb7bab6eea6c323925cae8215 to your computer and use it in GitHub Desktop.
Save Cedev/c9f3769eb7bab6eea6c323925cae8215 to your computer and use it in GitHub Desktop.
tape comonad
{-# language DeriveFunctor #-}
{-# language FlexibleInstances #-}
import Data.Function
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
kfix :: ComonadApply w => w (w a -> a) -> w a
kfix w = fix $ \u -> w <@> duplicate u
class Comonad w => ComonadApply w where
(<@>) :: w (a -> b) -> w a -> w b
data Stream a = Stream a (Stream a)
deriving (Show, Eq, Functor)
advance :: Stream a -> Stream a
advance ~(Stream _ s) = s
iterateS :: (a -> a) -> a -> Stream a
iterateS f x = Stream x (iterateS f (f x))
repeatS :: a -> Stream a
repeatS a = fix (Stream a)
toList :: Stream a -> [a]
toList (Stream a s) = a:toList s
instance Comonad Stream where
extract ~(Stream a _) = a
duplicate w = iterateS advance w
instance ComonadApply Stream where
~(Stream f fs) <@> ~(Stream a as) = Stream (f a) (fs <@> as)
data Tape a = Tape (Stream a) a (Stream a)
deriving (Show, Eq, Functor)
moveLeft :: Tape a -> Tape a
moveLeft ~(Tape ~(Stream l ls) a rs) = Tape ls l (Stream a rs)
moveRight :: Tape a -> Tape a
moveRight ~(Tape ls a ~(Stream r rs)) = Tape (Stream a ls) r rs
{-
productively :: Tape a -> Tape a
productively ~(Tape ls a rs) = Tape ls a rs
moveLeft, moveRight :: Tape a -> Tape a
moveLeft w = productively $
case w of
Tape [] _ _ -> w
Tape (l:ls) a rs -> Tape ls l (a:rs)
moveRight w = productively $
case w of
Tape _ _ [] -> w
Tape ls a (r:rs) -> Tape (a:ls) r rs
-}
instance Comonad Tape where
extract ~(Tape _ a _) = a
duplicate w@(~(Tape ls _ rs)) = Tape lefts w rights
where
lefts = advance $ iterateS moveLeft w
rights = advance $ iterateS moveRight w
instance ComonadApply Tape where
~(Tape l f r) <@> ~(Tape l' a r') = Tape (l <@> l') (f a) (r <@> r')
rightBy :: Int -> Tape a -> a
rightBy x w | x >= 0 = extract $ iterate moveRight w !! x
| x < 0 = leftBy (-x) w
leftBy :: Int -> Tape a -> a
leftBy x w | x >= 0 = extract $ iterate moveLeft w !! x
| x < 0 = rightBy (-x) w
stream :: [a] -> a -> Stream a
stream [] bg = repeatS bg
stream (a:as) bg = Stream a (stream as bg)
tape :: a -> [a] -> a -> Tape a
tape left middle right = Tape (repeatS left) a s
where
(Stream a s) = stream middle right
tapeKFix :: Tape Int
tapeKFix = kfix $ tape (const 0) [const 1, const 1] ((+) <$> leftBy 2 <*> leftBy 1)
main = print $ fmap extract $ take 100 $ iterate moveRight $ tapeKFix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment