Малоизвестный факт: если вы включите достаточное количество расширений языка (ghc), Haskell станет интерпретируемым языком с динамической типизацией! Например, следующая программа реализует сложение.
{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Zero
data Succ a
class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)
Это больше не похоже на Haskell. Для одного вместо того, чтобы работать над объектами, мы работаем над типами. Каждый номер - это его собственный тип. Вместо функций у нас есть классы типов. Функциональные зависимости позволяют нам использовать их как функции между типами.
Итак, как мы можем вызвать наш код? Мы используем другой класс
class Test a | -> a
where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
=> Test a
Это устанавливает тип test
для типа 4 + 3. Если мы откроем это в ghci, мы обнаружим, что test
он действительно имеет тип 7:
Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))
задача
Я хочу, чтобы вы реализовали класс, который умножает две цифры Пеано (неотрицательные целые числа). Числа Пеано будут построены с использованием тех же типов данных в примере выше:
data Zero
data Succ a
И ваш класс будет оцениваться так же, как и выше. Вы можете назвать свой класс как хотите.
Вы можете использовать любые расширения языка GHC, которые вы хотите, бесплатно для байтов.
Тестовые случаи
В этих тестах предполагается, что ваш класс назван M
, вы можете назвать его как-нибудь еще, если хотите.
class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a
class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a
class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a
class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a
Результаты
*Main> :t test1
test1
:: Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
:: Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ
(Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))
Черпает вдохновение в наборе технических интервью