1
1
{-# LANGUAGE NoImplicitPrelude #-}
2
2
module ITMOPrelude.Primitive where
3
3
4
- import Prelude (Show ,Read )
4
+ import Prelude (Show ,Read , error )
5
5
6
6
---------------------------------------------
7
7
-- Синтаксис лямбда-выражений
@@ -66,7 +66,10 @@ natOne = Succ Zero -- 1
66
66
67
67
-- Сравнивает два натуральных числа
68
68
natCmp :: Nat -> Nat -> Tri
69
- natCmp = undefined
69
+ natCmp Zero Zero = EQ
70
+ natCmp Zero (Succ _) = LE
71
+ natCmp (Succ _) Zero = GT
72
+ natCmp (Succ n) (Succ m) = natCmp n m
70
73
71
74
-- n совпадает с m
72
75
natEq :: Nat -> Nat -> Bool
@@ -91,7 +94,9 @@ Zero +. m = m
91
94
infixl 6 -.
92
95
-- Вычитание для натуральных чисел
93
96
(-.) :: Nat -> Nat -> Nat
94
- n -. m = undefined
97
+ Zero -. n = Zero
98
+ n -. Zero = n
99
+ (Succ n) -. (Succ m) = n -. m
95
100
96
101
infixl 7 *.
97
102
-- Умножение для натуральных чисел
@@ -101,83 +106,144 @@ Zero *. m = Zero
101
106
102
107
-- Целое и остаток от деления n на m
103
108
natDivMod :: Nat -> Nat -> Pair Nat Nat
104
- natDivMod n m = undefined
109
+ natDivMod n m = case compare of
110
+ LE -> Pair Zero n
111
+ EQ -> Pair natOne Zero
112
+ GT -> let rec = natDivMod (n -. m) m in
113
+ Pair (Succ $ fst rec ) (snd rec )
114
+ where compare = natCmp n m
105
115
106
116
natDiv n = fst . natDivMod n -- Целое
107
117
natMod n = snd . natDivMod n -- Остаток
108
118
109
119
-- Поиск GCD алгоритмом Евклида (должен занимать 2 (вычислителельная часть) + 1 (тип) строчки)
110
120
gcd :: Nat -> Nat -> Nat
111
- gcd = undefined
121
+ gcd n Zero = n
122
+ gcd n m = gcd m (n `natMod` m)
112
123
113
124
-------------------------------------------
114
125
-- Целые числа
115
126
116
127
-- Требуется, чтобы представление каждого числа было единственным
117
- data Int = UNDEFINED deriving (Show ,Read )
128
+ data Int =
129
+ Positive Nat |
130
+ NegativeMinusOne Nat
131
+ deriving (Show ,Read )
118
132
119
- intZero = undefined -- 0
120
- intOne = undefined -- 1
121
- intNegOne = undefined -- -1
133
+ natural (Positive n) = n
134
+ natural (NegativeMinusOne _) = error " natural: negative Integer"
135
+
136
+ fromNatural = Positive
137
+
138
+ intZero = Positive Zero
139
+ intOne = Positive $ Succ Zero
140
+ intNegOne = NegativeMinusOne Zero
122
141
123
142
-- n -> - n
124
143
intNeg :: Int -> Int
125
- intNeg = undefined
144
+ intNeg (Positive Zero ) = Positive Zero
145
+ intNeg (Positive (Succ n)) = NegativeMinusOne n
146
+ intNeg (NegativeMinusOne n) = Positive $ Succ n
147
+
148
+ intAbs (NegativeMinusOne n) = Positive $ Succ n
149
+ intAbs n = n
126
150
127
151
-- Дальше также как для натуральных
128
152
intCmp :: Int -> Int -> Tri
129
- intCmp = undefined
153
+ intCmp (Positive n) (Positive m) = natCmp n m
154
+ intCmp (NegativeMinusOne _) (Positive _) = LE
155
+ intCmp (Positive _) (NegativeMinusOne _) = GT
156
+ intCmp (NegativeMinusOne n) (NegativeMinusOne m) = natCmp m n
130
157
131
158
intEq :: Int -> Int -> Bool
132
- intEq = undefined
159
+ intEq n m = case intCmp n m of
160
+ EQ -> True
161
+ otherwise -> False
133
162
134
163
intLe :: Int -> Int -> Bool
135
- intLe = undefined
164
+ intLe n m = case intCmp n m of
165
+ LE -> True
166
+ otherwise -> False
136
167
137
168
infixl 6 .+. , .-.
138
169
-- У меня это единственный страшный терм во всём файле
139
170
(.+.) :: Int -> Int -> Int
140
- n .+. m = undefined
171
+ (Positive n) .+. (Positive m) = Positive $ n +. m
172
+ (NegativeMinusOne n) .+. (NegativeMinusOne m) = NegativeMinusOne $ Succ (n +. m)
173
+ (Positive n) .+. (NegativeMinusOne m) =
174
+ if' (natLe n (Succ m))
175
+ (NegativeMinusOne $ m -. n)
176
+ (Positive $ n -. (Succ m))
177
+ n@ (NegativeMinusOne _) .+. m@ (Positive _) = m .+. n
141
178
142
179
(.-.) :: Int -> Int -> Int
143
180
n .-. m = n .+. (intNeg m)
144
181
145
182
infixl 7 .*.
146
183
(.*.) :: Int -> Int -> Int
147
- n .*. m = undefined
184
+ (Positive n) .*. (Positive m) = Positive $ n *. m
185
+ (NegativeMinusOne n) .*. (NegativeMinusOne m) = Positive $ (Succ n) *. (Succ m)
186
+ (Positive Zero ) .*. (NegativeMinusOne _) = Positive Zero
187
+ (Positive n) .*. (NegativeMinusOne m) = NegativeMinusOne $ (n *. (Succ m)) -. natOne
188
+ n@ (NegativeMinusOne _) .*. m@ (Positive _) = m .*. n
189
+
190
+ intSign (Positive Zero ) = intZero
191
+ intSign (Positive (Succ _)) = intOne
192
+ intSign (NegativeMinusOne _) = intNegOne
193
+
194
+ intDiv :: Int -> Int -> Int
195
+ intDiv (Positive n) (Positive m) = Positive $ natDiv n m
196
+ intDiv n m = intSign n .*. intSign m .*. (intAbs n `intDiv` intAbs m)
148
197
149
198
-------------------------------------------
150
199
-- Рациональные числа
151
200
152
- data Rat = Rat Int Nat
201
+ data Rat = Rat Int Nat deriving ( Show , Read )
153
202
154
203
ratNeg :: Rat -> Rat
155
204
ratNeg (Rat x y) = Rat (intNeg x) y
156
205
157
206
-- У рациональных ещё есть обратные элементы
158
207
ratInv :: Rat -> Rat
159
- ratInv = undefined
208
+ ratInv ( Rat x y) = Rat (intSign x .*. Positive y) (natural . intAbs $ x)
160
209
161
210
-- Дальше как обычно
162
211
ratCmp :: Rat -> Rat -> Tri
163
- ratCmp = undefined
212
+ ratCmp (Rat xNum xDenom) (Rat yNum yDenom) =
213
+ if' (natEq xDenom yDenom)
214
+ (intCmp xNum yNum)
215
+ (ratCmp newX newY)
216
+ where newX = Rat (xNum .*. fromNatural yDenom) (xDenom *. yDenom)
217
+ newY = Rat (yNum .*. fromNatural xDenom) (yDenom *. xDenom)
164
218
165
219
ratEq :: Rat -> Rat -> Bool
166
- ratEq = undefined
220
+ ratEq n m = case ratCmp n m of
221
+ EQ -> True
222
+ otherwise -> False
167
223
168
224
ratLe :: Rat -> Rat -> Bool
169
- ratLe = undefined
225
+ ratLe n m = case ratCmp n m of
226
+ LE -> True
227
+ otherwise -> False
228
+
229
+ ratReduce (Rat num denom) = Rat (num `intDiv` intGcd) (denom `natDiv` natGcd)
230
+ where natGcd = gcd (natural . intAbs $ num) (denom)
231
+ intGcd = fromNatural natGcd
170
232
171
233
infixl 7 %+ , %-
172
234
(%+) :: Rat -> Rat -> Rat
173
- n %+ m = undefined
235
+ (Rat xNum xDenom) %+ (Rat yNum yDenom) = ratReduce $ Rat newNumerator newDenominator
236
+ where denomN = fromNatural xDenom
237
+ denomM = fromNatural yDenom
238
+ newNumerator = (xNum .*. fromNatural yDenom) .+. (yNum .*. fromNatural xDenom)
239
+ newDenominator = xDenom *. yDenom
174
240
175
241
(%-) :: Rat -> Rat -> Rat
176
242
n %- m = n %+ (ratNeg m)
177
243
178
244
infixl 7 %* , %/
179
245
(%*) :: Rat -> Rat -> Rat
180
- n %* m = undefined
246
+ ( Rat xNum xDenom) %* ( Rat yNum yDenom) = ratReduce $ Rat (xNum .*. yNum) (xDenom *. yDenom)
181
247
182
248
(%/) :: Rat -> Rat -> Rat
183
249
n %/ m = n %* (ratInv m)
0 commit comments