-
-
Save deniok/5c93628c762df8a11ebfe57db676898b to your computer and use it in GitHub Desktop.
FP_HSE2020Fall_06
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE StandaloneDeriving #-} | |
{-# LANGUAGE RankNTypes #-} | |
module Fp06 where | |
-- Функции, равные экстенсионально, но не интенсионально | |
suc, suc' :: (forall a. (a -> a) -> a -> a) -> (a -> a) -> a -> a | |
suc = \n s z -> n s (s z) | |
suc' = \n s z -> s (n s z) | |
zero, one, two :: (a -> a) -> a -> a | |
zero = \s z -> z | |
one = \s z -> s z | |
two = \s z -> s (s z) | |
{- | |
*Fp06> suc two (+1) 0 | |
3 | |
*Fp06> suc' two (+1) 0 | |
3 | |
*Fp06> suc two ([42]++) [] | |
[42,42,42] | |
*Fp06> suc' two ([42]++) [] | |
[42,42,42] | |
-} | |
{- | |
Полиморфизм второго ранга необходим, чтобы мы не могли передавать | |
в качестве первого аргумента ничего, кроме чисел Черча. | |
Без него экстенсионального равенства нет | |
-} | |
suc'', suc''' :: ((a -> a) -> a -> a) -> (a -> a) -> a -> a | |
suc'' = \n s z -> n s (s z) | |
suc''' = \n s z -> s (n s z) | |
{- | |
Prelude> suc'' (\s z -> if z == 0 then 5 else 4) (+1) 0 | |
4 | |
Prelude> suc''' (\s z -> if z == 0 then 5 else 4) (+1) 0 | |
6 | |
-} | |
-- Производные представители (Derived Instances) | |
data Point a = Point a a | |
deriving Eq | |
-- Point 3 5 == Point 3 5 | |
-- В GHC можно и отдельно | |
-- (подключив расширение StandaloneDeriving) | |
deriving instance Show a => Show (Point a) | |
{- | |
GHCi> Point 3 5 | |
Point 3 5 | |
-} | |
-- вспомогательная эмуляция низкоуровневой реализации | |
eqInt :: Int -> Int -> Bool | |
eqInt x y = x == y | |
-- словарь для Eq', то есть запись из его методов | |
data Eq' a = MkEq { eq,ne :: a -> a -> Bool } | |
-- функции-селекторы выбирают методы равенства и неравенства из этого словаря | |
{- | |
GHCi> :t eq | |
eq :: Eq' a -> a -> a -> Bool | |
GHCi> :t ne | |
ne :: Eq' a -> a -> a -> Bool | |
-} | |
-- объявления instance транслируются в функции, возвращающие словарь... | |
dEqInt :: Eq' Int | |
dEqInt = MkEq { | |
eq = eqInt, | |
ne = \x y -> not $ eqInt x y | |
} | |
-- ... или в функции, принимающие некоторый словарь и возвращающие более сложный словарь | |
dEqList :: Eq' a -> Eq' [a] | |
dEqList (MkEq e _) = MkEq { | |
eq = el, | |
ne = \x y -> not $ el x y | |
} where | |
el [] [] = True | |
el (x:xs) (y:ys) = x `e` y && xs `el` ys | |
el _ _ = False | |
-- Функция elem теперь принимает словарь в качестве явного параметра | |
elem' :: Eq' a -> a -> [a] -> Bool | |
elem' _ _ [] = False | |
elem' d x (y:ys) = eq d x y || elem' d x ys | |
{- | |
GHCi> elem' dEqInt 2 [3,5,2] | |
True | |
GHCi> elem' dEqInt 2 [3,5,7] | |
False | |
GHCi> elem' (dEqList dEqInt) [3,5] [[4],[1,2,3],[3,5]] | |
True | |
GHCi> elem' (dEqList dEqInt) [3,5] [[4],[1,2,3],[3,8]] | |
False | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment