data [a] = [] | a:[a] -- , [] : — , [] —
head x:_ = x; tail _:x = x;
data () = () -- ,
[]==[] = True; (a:as)==(b:bs) = (a==b) && (as==bs)
[]==[] = True; (a:as)==(b:bs) = (a==b) && (as==bs)
provided that the elements are comparable.type N = [](); -- [()]
data Natural = MkN N; -- ,
toList :: Natural -> N; --
toList (MkN x) = x;
incN :: Natural -> Natural; -- ,
incN = MkN.(():).toList;
--
sumN :: Natural -> Natural -> Natural;
sumN (MkN x) = MkN.(++x).toList;
copy :: a->[a]; copy x = x: copy x;
concatAll :: [[a]] -> [a];
concatAll = foldl(++)[];
table :: Natural -> a -> [a]; --
table xy = map (\_->y) $ toList x;
-- a*b a b (),
-- b a ( , )
-- concatAll
multN :: Natural -> Natural -> Natural;
multN xy = MkN $ concatAll $ table x (toList y);
decN :: Natural -> Natural;
decN (MkN(_:xs)) = MkN xs;
decN (MkN []) = error "Cannot decrease 0 staying being Natural";
zeroN :: Natural;
zeroN = MkN [];
oneN :: Natural;
oneN = MkN [()];
equalN :: Natural -> Natural -> Bool;
equalN (MkN a) (MkN b) = a==b;
subN :: Natural -> Natural -> Natural;
subN xy | y==oneN = decN x -- x-1=decN(x)
| y/=zeroN = decN $ subN x $ decN y -- xy=(x-1)-(y-1)
| True = x; -- x-0=x
divmodN :: Natural -> Natural -> (Natural, Natural);
divmodN (MkN []) _ = error "cannot divide by zero";
divmodN base x | moreThanN base x = (zeroN, x)
| True = let (d,m) = divmodN base (subN x base) in (incN d,m);
moreThanN :: Natural -> Natural -> Bool;
moreThanN (MkN []) _ = False;
moreThanN _ (MkN []) = True;
moreThanN xy = moreThanN (decN x) (decN y);
lengthN :: [a] -> Natural;
lengthN = MkN . map (\_->());
data Integer = Positive Natural | Negative Natural;
absInt :: Integer -> Natural;
absInt (Positive x) = x;
absInt (Negative x) = x;
equalInt :: Integer -> Integer -> Bool;
equalInt (Positive x) (Positive y) = x `equalN` y;
equalInt (Negative x) (Negative y) = x `equalN` y;
equalInt (Negative x) (Positive y) | x==zeroN && y==zeroN = True;
equalInt (Positive x) (Negative y) | x==zeroN && y==zeroN = True;
equalInt _ _ = False;
negate :: Integer -> Integer;
negate (Positive x) = (Negative x);
negate (Negative x) = (Positive x);
sumInt :: Integer -> Integer -> Integer;
sumInt (Positive x) (Positive y) = Positive (sumN xy);
sumInt (Positive x) (Negative y) = if x `moreThanN` y then Positive (subN xy) else Negative (subN yx);
sumInt (Negative x) (Positive y) = if y `moreThanN` x then Positive (subN yx) else Negative (subN xy);
sumInt (Negative x) (Negative y) = Negative (sumN xy);
figures = ['0', '1', '2'];
naturalseries = zeroInt : map incInt naturalseries;
figuretoInt = compare $ zip figures naturalseries where{compare ((a,b):c) x | a==x = b | True = compare cx;};
inttoFigure = getElement figures where {getElement (h:t) n = if n==zeroInt then h else getElement t $ decInt n;};
base :: Integer;
base = lengthInt figures;
showInt :: Integer -> [Char];
showInt x | x<zeroInt = '-' : showInt (negate x)
| x==zeroInt = "0"
| x<base = [inttoFigure x]
| True = let (d,m) = divmodInt base x
in (show d) ++ [inttoFigure m];
readInt :: [Char] -> (Integer, [Char]);
readInt "" = error "No integer to read on input";
readInt str@(f:r)
| f=='-' = let (i,s) = readInt r in (negate i,s)
| f=='+' = readInt r
| True = let (num,rest) = split str in (parse $ map figuretoInt num, rest);
split :: [Char] -> ([Char],[Char]);
split "" = ("","");
split (x:y) | x~->figures = let (a,b)=split y in (x:a,b)
| True = ("", x:y);
parse :: [Integer] -> Integer;
parse = foldl (\g h->sumInt h $ multInt base g) zeroInt;
(~->) :: (Eq a) => a -> [a] -> Bool;
a ~-> [] = False;
a ~-> (b:c) = (a==b) || (a ~-> c);
(~->) :: (Eq a) => a -> [a] -> Bool;
a ~-> [] = False;
a ~-> (b:c) = (a==b) || (a ~-> c);
Source: https://habr.com/ru/post/111063/
All Articles