├── README.md └── stepic ├── Fib.hs ├── GorkMorkClassTypes.hs ├── Hello.hs ├── SafeEnum.hs ├── Seq.hs ├── Test.hs ├── avg.hs ├── divergence.hs ├── doItYourself.hs ├── evenOnly.hs ├── importModule.hs ├── integration.hs ├── isPalindrom.hs ├── isPrime.hs ├── multSecond.hs ├── oddsOnly.hs ├── on3.hs ├── printable.hs ├── secondArgument.hs ├── seqA.hs ├── sumNCount.hs └── sumNCount2.hs /README.md: -------------------------------------------------------------------------------- 1 | A pile of haskell exercises, the tasks are mostly from the [stepic.org] haskell course. 2 | 3 | [stepic.org]: https://stepic.org/ 4 | -------------------------------------------------------------------------------- /stepic/Fib.hs: -------------------------------------------------------------------------------- 1 | fibonacci :: Integer -> Integer 2 | fibonacci n = helper (signum n) 1 ((-1) * signum n) n 3 | 4 | helper sign prev pprev n | n == 0 = pprev + (prev * sign) 5 | | n > 0 = helper sign (prev + pprev) prev (n-1) 6 | | n < 0 = helper sign (pprev - prev) prev (n+1) 7 | -------------------------------------------------------------------------------- /stepic/GorkMorkClassTypes.hs: -------------------------------------------------------------------------------- 1 | class KnownToGork a where 2 | stomp :: a -> a 3 | doesEnrageGork :: a -> Bool 4 | 5 | class KnownToMork a where 6 | stab :: a -> a 7 | doesEnrageMork :: a -> Bool 8 | 9 | class (KnownToGork a, KnownToMork a) => KnownToGorkAndMork a where 10 | stompOrStab :: a -> a 11 | stompOrStab x 12 | | doesEnrageMork x == True && doesEnrageGork x == True 13 | = (stomp . stab) x 14 | | doesEnrageMork x == True 15 | = stomp x 16 | | doesEnrageGork x == True 17 | = stab x 18 | | otherwise = x 19 | -------------------------------------------------------------------------------- /stepic/Hello.hs: -------------------------------------------------------------------------------- 1 | main = putStrLn "Hello, world!" 2 | -------------------------------------------------------------------------------- /stepic/SafeEnum.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Реализуйте класс типов 3 | 4 | class SafeEnum a where 5 | ssucc :: a -> a 6 | spred :: a -> a 7 | обе функции которого ведут себя как succ и pred стандартного класса Enum, однако являются тотальными, то есть не останавливаются с ошибкой на наибольшем и наименьшем значениях типа-перечисления соответственно, а обеспечивают циклическое поведение. Ваш класс должен быть расширением ряда классов типов стандартной библиотеки, так чтобы можно было написать реализацию по умолчанию его методов, позволяющую объявлять его представителей без необходимости писать какой бы то ни было код. Например, для типа Bool должно быть достаточно написать строку 8 | 9 | instance SafeEnum Bool 10 | и получить возможность вызывать 11 | 12 | GHCi> ssucc False 13 | True 14 | GHCi> ssucc True 15 | False 16 | -} 17 | 18 | class (Eq a, Enum a, Bounded a) => SafeEnum a where 19 | ssucc :: a -> a 20 | ssucc n 21 | | n == maxBound = minBound 22 | | otherwise = succ n 23 | 24 | spred :: a -> a 25 | spred n 26 | | n == minBound = maxBound 27 | | otherwise = pred n 28 | 29 | instance SafeEnum Bool 30 | -------------------------------------------------------------------------------- /stepic/Seq.hs: -------------------------------------------------------------------------------- 1 | seqA :: Integer -> Integer 2 | seqA' 0 = 1 3 | seqA' 1 = 2 4 | seqA' 2 = 3 5 | seqA' n = seqA (n-1) + seqA (n-2) - 2 * seqA (n-3) 6 | -------------------------------------------------------------------------------- /stepic/Test.hs: -------------------------------------------------------------------------------- 1 | module Test where 2 | 3 | sayHello = putStrLn "Hello" 4 | -------------------------------------------------------------------------------- /stepic/avg.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Напишите функцию с сигнатурой: 3 | 4 | avg :: Int -> Int -> Int -> Double 5 | вычисляющую среднее значение переданных в нее аргументов: 6 | 7 | GHCi> avg 3 4 8 8 | 5.0 9 | -} 10 | 11 | avg :: Int -> Int -> Int -> Double 12 | avg a b c = fromIntegral (a + b + c) / 3 13 | -------------------------------------------------------------------------------- /stepic/divergence.hs: -------------------------------------------------------------------------------- 1 | --Отметьте функции, которые не могут привести к расходимости ни на каком корректном наборе аргументов. 2 | 3 | foo a = a 4 | 5 | bar = const foo 6 | 7 | baz x = const True --ok 8 | 9 | quux = let x = x in x 10 | 11 | corge = 10 --ok 12 | 13 | grault x 0 = x 14 | grault x y = x 15 | 16 | garply = grault 'q' 17 | 18 | waldo = foo 19 | 20 | -- Try to pass undefined to each function 21 | -------------------------------------------------------------------------------- /stepic/doItYourself.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Функция одной переменной doItYourself выбирает наибольшее из переданного ей аргумента и числа 42, затем возводит результат выбора в куб и, наконец, вычисляет логарифм по основанию 2 от полученного числа. Эта функция реализована в виде: 3 | 4 | doItYourself = f . g . h 5 | Напишите реализации функций f, g и h. Постарайтесь сделать это в бесточечном стиле. 6 | -} 7 | 8 | doItYourself = f . g . h 9 | 10 | f = (logBase 2) 11 | 12 | g = (^3) 13 | 14 | h = (max 42) 15 | -------------------------------------------------------------------------------- /stepic/evenOnly.hs: -------------------------------------------------------------------------------- 1 | evenOnly :: [a] -> [a] 2 | evenOnly = (\(fst,_,_) -> fst) . foldr (f) ([],[],True) where 3 | f a ~(xs,ys,True) = (a:xs,ys,False) 4 | f a ~(xs,ys,_) = (xs,a:ys,True) 5 | 6 | -------------------------------------------------------------------------------- /stepic/importModule.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Что произойдет при попытке загрузить данный модуль в GHCi? 3 | 4 | Все пройдет нормально 5 | ·Произойдет ошибка из-за несовпадения типа аргумента и ожидаемого типа функции 6 | Произойдет ошибка из-за неопределенности при выборе функции 7 | -} 8 | 9 | module Test where 10 | import Data.List hiding (union) 11 | import Data.Set 12 | 13 | myUnion [] ys = ys 14 | myUnion xs ys = union xs ys 15 | -------------------------------------------------------------------------------- /stepic/integration.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Реализуйте функцию, находящую значение определённого интеграла от заданной функции ff на заданном интервале [a,b][a,b] методом трапеций. (Используйте равномерную сетку; достаточно 1000 элементарных отрезков.) 3 | 4 | integration :: (Double -> Double) -> Double -> Double -> Double 5 | integration f a b = undefined 6 | GHCi> integration sin pi 0 7 | -2.0 8 | Результат может отличаться от -2.0, но не более чем на 1e-4. 9 | -} 10 | 11 | 12 | integration :: (Double -> Double) -> Double -> Double -> Double 13 | integration f a b = integ f a b 1000 where 14 | integ f a b 0 = 0 15 | integ f a b n = h * (f (a) + f (a + h)) / 2 + integ f (a + h) b (n - 1) where h = (b - a) / n 16 | -------------------------------------------------------------------------------- /stepic/isPalindrom.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Реализуйте функцию isPalindrome, которая определеяет, является ли переданный ей список палиндромом. 3 | 4 | GHCi> isPalindrome "saippuakivikauppias" 5 | True 6 | GHCi> isPalindrome [1] 7 | True 8 | GHCi> isPalindrome [1, 2] 9 | False 10 | -} 11 | 12 | isPalindrome :: Eq a => [a] -> Bool 13 | isPalindrome a = a == reverse a 14 | 15 | -- Is it possible to write it without mentioning a explicitly? 16 | -------------------------------------------------------------------------------- /stepic/isPrime.hs: -------------------------------------------------------------------------------- 1 | isPrime :: Integer -> Bool 2 | isPrime n = h n 2 where 3 | h n b 4 | | b > (round $ sqrt $ fromIntegral n) = True 5 | | n `mod` b == 0 = False 6 | | otherwise = h n (b+1) 7 | -------------------------------------------------------------------------------- /stepic/multSecond.hs: -------------------------------------------------------------------------------- 1 | {- 2 | В модуле Data.Function определена полезная функция высшего порядка 3 | 4 | on :: (b -> b -> c) -> (a -> b) -> a -> a -> c 5 | on op f x y = f x `op` f y 6 | Она принимает четыре аргумента: бинарный оператор с однотипными аргументами (типа b), функцию f :: a -> b, возвращающую значение типа b, и два значения типа a. Функция on применяет f дважды к двум значениям типа a и передает результат в бинарный оператор. 7 | 8 | Используя on можно, например, записать функцию суммирования квадратов аргументов так: 9 | 10 | sumSquares = (+) `on` (^2) 11 | Функция multSecond, перемножающая вторые элементы пар, реализована следующим образом 12 | 13 | multSecond = g `on` h 14 | 15 | g = undefined 16 | 17 | h = undefined 18 | Напишите реализацию функций g и h. 19 | -} 20 | 21 | 22 | import Data.Function 23 | 24 | multSecond = g `on` h 25 | 26 | g = (*) 27 | 28 | h = snd 29 | -------------------------------------------------------------------------------- /stepic/oddsOnly.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Сформируйте список целых чисел, содержащий только те элементы исходного списка, значение которых нечетно. 3 | 4 | GHCi> oddsOnly [2,5,7,10,11,12] 5 | [5,7,11] 6 | Для анализа четности можно использовать функции odd и even стандартной библиотеки. 7 | -} 8 | 9 | oddsOnly :: Integral a => [a] -> [a] 10 | oddsOnly = filter odd 11 | -------------------------------------------------------------------------------- /stepic/on3.hs: -------------------------------------------------------------------------------- 1 | {-| 2 | Реализуйте функцию on3, имеющую семантику, схожую с on, но принимающую в качестве первого аргумента трехместную функцию 3 | 4 | Например, сумма квадратов трех чисел может быть записана с использованием on3 так 5 | 6 | GHCi> let sum3squares = (\x y z -> x+y+z) `on3` (^2) 7 | GHCi> sum3squares 1 2 3 8 | 14 9 | -} 10 | 11 | 12 | on3 :: (b -> b -> b -> c) -> (a -> b) -> a -> a -> a -> c 13 | on3 op f x y z = op (f x) (f y) (f z) 14 | -------------------------------------------------------------------------------- /stepic/printable.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Реализуйте класс типов Printable, предоставляющий один метод toString — функцию одной переменной, которая преобразует значение типа, являющегося представителем Printable, в строковое представление. 3 | 4 | Сделайте типы данных Bool и () представителями этого класса типов, обеспечив следующее поведение: 5 | 6 | GHCi> toString True 7 | "true" 8 | GHCi> toString False 9 | "false" 10 | GHCi> toString () 11 | "unit type" 12 | 13 | Сделайте тип пары представителем класса типов Printable, реализованного вами в предыдущей задаче, обеспечив следующее поведение: 14 | 15 | GHCi> toString (False,()) 16 | "(false,unit type)" 17 | GHCi> toString (True,False) 18 | "(true,false)" 19 | 20 | -} 21 | 22 | class Printable a where 23 | toString :: a -> String 24 | 25 | instance Printable Bool where 26 | toString True = "true" 27 | toString False = "false" 28 | 29 | instance Printable () where 30 | toString _ = "unit type" 31 | 32 | instance (Printable a, Printable b) => Printable (a,b) where 33 | toString pair = "(" ++ (toString $ fst pair) ++ "," ++ (toString $ snd pair) ++ ")" 34 | -------------------------------------------------------------------------------- /stepic/secondArgument.hs: -------------------------------------------------------------------------------- 1 | -- Напишите функцию трех аргументов getSecondFrom, полиморфную по каждому из них, которая полностью игнорирует первый и третий аргумент, а возвращает второй. Укажите ее тип. 2 | 3 | getSecondFrom :: a -> b -> c -> b 4 | getSecondFrom a b c = b 5 | -------------------------------------------------------------------------------- /stepic/seqA.hs: -------------------------------------------------------------------------------- 1 | seqA :: Integer -> Integer 2 | seqA n = 3 | let seq = 1 : 2 : 3 : zipWith (-) (zipWith (+) (tail (tail seq)) (tail seq)) (map ((*)2) seq) in 4 | seq !! (fromIntegral n) 5 | -------------------------------------------------------------------------------- /stepic/sumNCount.hs: -------------------------------------------------------------------------------- 1 | sum'n'count :: Integer -> (Integer, Integer) 2 | sum'n'count 0 = (0,1) 3 | sum'n'count x = (sum,count) where 4 | x' = abs x 5 | sum = sumd x' 0 6 | count = cd x' 0 7 | sumd 0 acc = acc 8 | sumd x' acc = sumd (div x' 10) (acc + (mod x' 10)) 9 | cd 0 acc = acc 10 | cd x' acc = cd (div x' 10) (acc + 1) 11 | -------------------------------------------------------------------------------- /stepic/sumNCount2.hs: -------------------------------------------------------------------------------- 1 | sum'n'count :: Integer -> (Integer, Integer) 2 | sum'n'count x = (sumd x, countd x) where 3 | rund 0 f acc = acc 4 | rund x f acc = rund (div x 10) f (acc + f x) 5 | rund0 x f = (flip rund) 0 6 | sumd x = rund0 x (mod x 10) 7 | countd x = rund0 x 1 8 | --------------------------------------------------------------------------------