Browse Source

Create texteditor.hs

Abhinav Sarkar 4 years ago
parent
commit
33e874d29f
1 changed files with 79 additions and 0 deletions
  1. 79
    0
      2016-04-05/texteditor.hs

+ 79
- 0
2016-04-05/texteditor.hs View File

@@ -0,0 +1,79 @@
1
+module TextEditor where
2
+
3
+import Data.Monoid ((<>), Sum(..))
4
+
5
+data JoinList m a = Empty | Value m a | JoinList m (JoinList m a) (JoinList m a)
6
+                    deriving (Show, Eq)
7
+
8
+meta :: (Monoid m) => JoinList m a -> m
9
+meta Empty = mempty
10
+meta (Value m _) = m
11
+meta (JoinList m _ _ ) = m
12
+
13
+instance Monoid m => Monoid (JoinList m a) where
14
+  mempty = Empty
15
+
16
+  mappend Empty x = x
17
+  mappend x Empty = x
18
+  mappend left right = JoinList (meta left <> meta right) left right
19
+
20
+instance Functor (JoinList m) where
21
+  fmap _ Empty = Empty
22
+  fmap f (Value m x) = Value m (f x)
23
+  fmap f (JoinList m left right) = JoinList m (fmap f left) (fmap f right)
24
+
25
+instance Foldable (JoinList m) where
26
+  foldMap _ Empty = mempty
27
+  foldMap f (Value _ x) = f x
28
+  foldMap f (JoinList _ left right) = foldMap f left <> foldMap f right
29
+
30
+data Meta = Meta { lineCount :: Sum Int
31
+                 , letterCount :: Sum Int
32
+                 , wordCount :: Sum Int
33
+                 } deriving (Show)
34
+
35
+instance Monoid Meta where
36
+  mempty = Meta mempty mempty mempty
37
+  mappend (Meta a b c) (Meta x y z) = Meta (a <> x) (b <> y) (c <> z)
38
+
39
+mkMeta :: String -> Meta
40
+mkMeta x = Meta (Sum 1) (Sum . length $ x) (Sum . length . words $ x)
41
+
42
+type Text = JoinList Meta String
43
+
44
+fromList :: [String] -> Text
45
+fromList []  = Empty
46
+fromList [x] = Value (mkMeta x) x
47
+fromList xs  =
48
+  let (left, right) = splitAt (length xs `div` 2) xs
49
+  in fromList left <> fromList right
50
+
51
+getAt :: Int -> Text -> Maybe String
52
+getAt 1 (Value _ x)             = Just x
53
+getAt n (JoinList _ left right) =
54
+  let l = getSum . lineCount . meta $ left
55
+  in if n <= l
56
+    then getAt n left
57
+    else getAt (n - l) right
58
+getAt _ _                       = Nothing
59
+
60
+transform :: Int -> String -> Text -> (Int -> String -> Text -> Maybe Text) -> Maybe Text
61
+transform n s (JoinList _ left right) f =
62
+  let l = getSum . lineCount . meta $ left
63
+  in if n <= l
64
+    then fmap (\e -> JoinList (meta e <> meta right) e right) $ f n s left
65
+    else fmap (\e -> JoinList (meta left <> meta e) left e) $ f (n - l) s right
66
+transform _ _ _ _ = Nothing
67
+
68
+editAt :: Int -> String -> Text -> Maybe Text
69
+editAt 1 s (Value _ _)   = Just (Value (mkMeta s) s)
70
+editAt n s l@JoinList {} = transform n s l editAt
71
+editAt _ _ _             = Nothing
72
+
73
+insertAt :: Int -> String -> Text -> Maybe Text
74
+insertAt 1 s Empty         = Just $ Value (mkMeta s) s
75
+insertAt 1 s v@(Value _ _) =
76
+  let left = Value (mkMeta s) s
77
+  in Just (JoinList (meta left <> meta v) left v)
78
+insertAt n s l@JoinList {} = transform n s l insertAt
79
+insertAt _ _ _             = Nothing

Loading…
Cancel
Save