Skip to content

Commit bc99917

Browse files
committed
Primitives
1 parent f7020ed commit bc99917

File tree

1 file changed

+88
-22
lines changed

1 file changed

+88
-22
lines changed

ITMOPrelude/Primitive.hs

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{-# LANGUAGE NoImplicitPrelude #-}
22
module ITMOPrelude.Primitive where
33

4-
import Prelude (Show,Read)
4+
import Prelude (Show,Read, error)
55

66
---------------------------------------------
77
-- Синтаксис лямбда-выражений
@@ -66,7 +66,10 @@ natOne = Succ Zero -- 1
6666

6767
-- Сравнивает два натуральных числа
6868
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
7073

7174
-- n совпадает с m
7275
natEq :: Nat -> Nat -> Bool
@@ -91,7 +94,9 @@ Zero +. m = m
9194
infixl 6 -.
9295
-- Вычитание для натуральных чисел
9396
(-.) :: Nat -> Nat -> Nat
94-
n -. m = undefined
97+
Zero -. n = Zero
98+
n -. Zero = n
99+
(Succ n) -. (Succ m) = n -. m
95100

96101
infixl 7 *.
97102
-- Умножение для натуральных чисел
@@ -101,83 +106,144 @@ Zero *. m = Zero
101106

102107
-- Целое и остаток от деления n на m
103108
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
105115

106116
natDiv n = fst . natDivMod n -- Целое
107117
natMod n = snd . natDivMod n -- Остаток
108118

109119
-- Поиск GCD алгоритмом Евклида (должен занимать 2 (вычислителельная часть) + 1 (тип) строчки)
110120
gcd :: Nat -> Nat -> Nat
111-
gcd = undefined
121+
gcd n Zero = n
122+
gcd n m = gcd m (n `natMod` m)
112123

113124
-------------------------------------------
114125
-- Целые числа
115126

116127
-- Требуется, чтобы представление каждого числа было единственным
117-
data Int = UNDEFINED deriving (Show,Read)
128+
data Int =
129+
Positive Nat |
130+
NegativeMinusOne Nat
131+
deriving (Show,Read)
118132

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
122141

123142
-- n -> - n
124143
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
126150

127151
-- Дальше также как для натуральных
128152
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
130157

131158
intEq :: Int -> Int -> Bool
132-
intEq = undefined
159+
intEq n m = case intCmp n m of
160+
EQ -> True
161+
otherwise -> False
133162

134163
intLe :: Int -> Int -> Bool
135-
intLe = undefined
164+
intLe n m = case intCmp n m of
165+
LE -> True
166+
otherwise -> False
136167

137168
infixl 6 .+., .-.
138169
-- У меня это единственный страшный терм во всём файле
139170
(.+.) :: 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
141178

142179
(.-.) :: Int -> Int -> Int
143180
n .-. m = n .+. (intNeg m)
144181

145182
infixl 7 .*.
146183
(.*.) :: 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)
148197

149198
-------------------------------------------
150199
-- Рациональные числа
151200

152-
data Rat = Rat Int Nat
201+
data Rat = Rat Int Nat deriving (Show, Read)
153202

154203
ratNeg :: Rat -> Rat
155204
ratNeg (Rat x y) = Rat (intNeg x) y
156205

157206
-- У рациональных ещё есть обратные элементы
158207
ratInv :: Rat -> Rat
159-
ratInv = undefined
208+
ratInv (Rat x y) = Rat (intSign x .*. Positive y) (natural . intAbs $ x)
160209

161210
-- Дальше как обычно
162211
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)
164218

165219
ratEq :: Rat -> Rat -> Bool
166-
ratEq = undefined
220+
ratEq n m = case ratCmp n m of
221+
EQ -> True
222+
otherwise -> False
167223

168224
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
170232

171233
infixl 7 %+, %-
172234
(%+) :: 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
174240

175241
(%-) :: Rat -> Rat -> Rat
176242
n %- m = n %+ (ratNeg m)
177243

178244
infixl 7 %*, %/
179245
(%*) :: Rat -> Rat -> Rat
180-
n %* m = undefined
246+
(Rat xNum xDenom) %* (Rat yNum yDenom) = ratReduce $ Rat (xNum .*. yNum) (xDenom *. yDenom)
181247

182248
(%/) :: Rat -> Rat -> Rat
183249
n %/ m = n %* (ratInv m)

0 commit comments

Comments
 (0)