{-# LANGUAGE ExistentialQuantification, RankNTypes #-} data Yoba = Yoba { imya :: String } data Chislo = Chislo { vladelec :: Yoba, znachenie :: forall a. (a -> a) -> (a -> a) } bratecYoba = Yoba { imya = "Bolshoi" } pravda = const lozh = flip pravda class PodobnoyeChislu m where sleduyusheeChisloPozhaluista :: m -> m predydusheeChisloPozhaluista :: m -> m nolLiEto :: m -> (a -> a -> a) nol :: m poschitayteVInteger :: m -> Integer poschitayteVInteger chislo | nolLiEto chislo True False = 0 | otherwise = 1 + poschitayteVInteger (predydusheeChisloPozhaluista chislo) instance PodobnoyeChislu Chislo where sleduyusheeChisloPozhaluista (Chislo { vladelec = vladelec, znachenie = znachenie }) = Chislo { vladelec = vladelec, znachenie = \f x -> znachenie f (f x) } predydusheeChisloPozhaluista (Chislo { vladelec = vladelec, znachenie = znachenie }) = Chislo { vladelec = vladelec, znachenie = \f x -> znachenie (\g h -> h (g f)) (const x) id } nolLiEto (Chislo { vladelec = vladelec, znachenie = znachenie }) = znachenie (const lozh) pravda nol = Chislo { vladelec = bratecYoba, znachenie = const id } maksimumTrehChisel :: PodobnoyeChislu m => m -> m -> m -> String maksimumTrehChisel a b c | nolLiEto a True False && nolLiEto b True False = "Tretye" | nolLiEto a True False && nolLiEto c True False = "Vtoroye" | nolLiEto b True False && nolLiEto c True False = "Pervoye" | otherwise = maksimumTrehChisel (predydusheeChisloPozhaluista a) (predydusheeChisloPozhaluista b) (predydusheeChisloPozhaluista c) -- ALLOU, YOBA, MENYA SLYSHNO? odin :: Chislo odin = sleduyusheeChisloPozhaluista nol dva = sleduyusheeChisloPozhaluista odin chetyre = sleduyusheeChisloPozhaluista $ sleduyusheeChisloPozhaluista dva main = putStrLn $ maksimumTrehChisel odin chetyre dva