- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
{- This code intentionally was made slightly cryptic -}
{-# LANGUAGE GADTs, StandaloneDeriving, UnicodeSyntax, KindSignatures, FlexibleInstances, LambdaCase, CPP, BangPatterns #-}
import System.Exit
import Data.Functor
import Control.Monad.IO.Class
import Control.Monad.Trans.Cont
import System.Random
import System.Posix.Signals
import System.Environment
import Control.Concurrent.MVar
instance Eq (Int → Int) where
_ == _ = True -- It's a hack
infixl 7 :.
data T ∷ * where {J, Â, Â', S, K ∷ T; (:.) ∷ T → T → T; Ψ ∷ {σ ∷ String} → T
;F ∷ (Int → Int) → T; N ∷ Int → T; Ø ∷ String → T}
parse ∷ String → [T] → T
parse ('f':'u':c) t = parse c (J:t)
parse ('b':'a':'r':c) t = parse c (Â:t)
parse ('~':c) (a:b:t) = parse c (b:.a:t)
parse ('~':_) _ = error "Parse error: missing operand(s)"
parse (_:c) t = parse c t
parse [] (h:_) = h :. Ψ []
parse [] [] = error "Parse error: empty program"
s ∷ T → T
s (J :. x) = (x :. S) :. K
s (K :. x :. _) = x
s (S :. x :. y :. z) = (x :. z) :. (y :. z)
s (F f :. N i) = N $ f i
s (F f :. F g) = F $ f . g
s (Â' :. N i :. ψ @ (Ψ {})) = ψ {σ = toEnum i : σ ψ}
s (Â :. n :. ψ @ (Ψ {})) = Â' :. (n :. F (+1) :. N 0) :. ψ
-- Other cases
s (a :. b) = (s a) :. (s b)
s x = x
eval ∷ (T → t) → (T → t) → T → t
eval fp done t | t == t' = done t
| otherwise = fp t'
where t' = s t
ψs a@Ψ{σ=s} = [(a, s)]
ψs (a:.b) = ψs a ++ ψs b
ψs _ = []
r' ∷ T → [(T, String)] -- Very inefficient; should be rewritten
r' a | null t = [(a, s)] where ((_, s):t) = ψs a
r' (a :. b) = r' a ++ r' b
r' _ = []
r ∷ T → IO (Maybe T)
r t = case r' t of
[] → return Nothing
t' → ((t' !!) <$> randomRIO (0, length t' - 1)) >>= \case
(Ψ{}, s) → putStrLn (reverse s) >> return Nothing
(t'', s) → putStrLn (reverse s) >> return (Just t'')
setMVar v = (tryTakeMVar v >>) . putMVar v
loop v f n = callCC $ \done → loop1 done (\fp → f fp done) n
where loop2 interrupt f' n = do
n' ← liftIO (readMVar v) >>= \case
0 → f' interrupt n
_ → callCC $ \fp → f' fp n
liftIO $ modifyMVar_ v $ (\k → return $ k-1)
loop2 interrupt f' n'
loop1 done f' n = do
n' ← callCC $ \int → loop2 int f' n
liftIO $ putStrLn "Measure (m) Abort (a) Continue (c) Run steps (number)"
(liftIO getLine) >>= \case
"a" → f' done n' >> return ()
"c" → liftIO $ setMVar v (-1)
"m" → liftIO (r n') >>= \case
Nothing → liftIO exitSuccess
Just n'' → loop1 done f' n'' >> return ()
a → case readsPrec 0 a of
(n,_):_ → liftIO $ setMVar v n
_ → liftIO $ putStrLn "Not understood."
loop1 done f' n'
main ∷ IO ()
main = do
(file, n) ← getArgs >>= \case
[f] → return (f, -1)
["-s", n, f] → case readsPrec 0 n of
(n',_):_ → return (f, n')
_ → error "Argument of -s should be a number"
_ → error "Insufficient arguments. Expected [-s NUMBER_OF_STEPS] FILE"
cnt ← newMVar n
installHandler keyboardSignal (Catch $ setMVar cnt 0) Nothing
void $ (r =<<) (evalContT $ loop cnt eval =<< (parse <$> readFile file))
люблю CLR и люблю функциональщину
но у меня на клавиатуре нету ψ, и потому мне он не подойдет
придется делать стартап на пхп
https://wiki.haskell.org/Haskell_in_industry
если у тебя в продакшене только пхп, это не значит что у других так же
ну вот я привел пример что пишут
что не так-то?
да, в целом функциональные языки как прекрсная дама: все программисты на них дрочат по ночам, а с утра идут писать тупой импетаривный бойлерплейтовый код
так ведь и на скале же пишут порой
Походу, там проще будет написать процессор, а под него уже компилить стрелялку обычным gcc...
Но лучше взять шланг: все таки llvm лучше позволяет делать бекенды
malbodge-процессор для защиты от реверса и патчей...
ножки должны называться @, C2 и ##.
Чтобы создатели обвязки епнулись
З.Ы. Там же троичная логика ещё... Так что ещё и по 3 логических уровня на ногах... Ну и двуполярное питание, как на советских операционниках... Тогда весь стандартный обвес сразу пролетает.
Отсюда: http://www.trinitas.ru/rus/doc/0226/002a/02260054.htm
Где бы найти эту свалку...
Врунишка. Каждый раз когда ты лжёшь где-то в мире на пхп обезьянами пишутся очередные даты. Не делай больше так.
Это к васе.
Просто читал об этом. Вот если бы реальный физический трит был - тогда совсем другое дело бы было.
"Так что ещё и по 3 логических уровня на ногах... Ну и двуполярное питание, как на советских операционниках..."
MLC флеш вон 4 варианта в одной ячейке хранит, а TLC - все 8. Именно уровнями. И ничто не мешает сделать 3 или 9. Так что физическая база есть, было бы желание и профит...
Просто никому нахуй не упёрлась непривычная троичная арифметика.
Триты же выгоднее в плане хранения информации.
Хотя если учесть какой пиздец начнется при переносе существующего кода на такие машины и то что некоторые бородатые прогеры до сих пор матерят Билли за ООП в винде...
Ну вот для хранения как раз юзают. Только не 3, а удобные для остальной схемы 4 и 8 уровней.
А логику и арифметику с тремя уровнями делать - тот ещё пиздец.
Купи FPGA, замути эмуляцию тритов через 2 бита и вперёд, хуярить троичный проц и портировать на него сишку ;)
Ну ты прям как немец мыслишь, что кроме своей специальности человек никогда ничего не осилит...
Если интересно что-то - бери да изучай, пока мозги не засохли да время есть (с работой будет меньше).
А ещё можно подобрать троичную «Сетунь» на свалке...
http://lurkmore.so/images/thumb/6/67/%D0%98%D0%B3%D0%BE%D1%80%D1%8C_%D1%82%D0%BE%D0%BD%D0%B5%D1%82.png/250px-%D0%98%D0%B3%D0%BE%D1%80%D1%8C_%D1%82%D0%BE%D0%BD%D0%B5%D1%82.png
ААААААААААААААА!!!!1111111111 Что ж ты делаешь, ирод? Я коллег перепугал хохотом. Думаю это агенты Путина
Дозиметром проверил?
А, так вот зачем у нас колбасу туалетной бумагой соей разбавляют... Заботятся о людях, значит.
Их либы даже человеку пересаживают.
И даже рисовали когда-то...
Я почти никогда ту часть проекта не собираю, только по праздникам. Проблем пока не было, но я и внутрь особенно не заглядывал.
Из /pr/ (а других ты и не знаешь)?
нормальные программеры любят хаскель
>/pr/
В самый раз, что не так?
я сказал что хорошие программисты любят хаскель
любит-ли его прыщепублика в /pr/. -- мне не ведомо
это же ты в /pr/ постоянно тусишь
"ты либо говно пиши, либо плохо обфусцируй"
Всё новое - это хорошо забытое старое? Interact?
короче, такая модель I/O, как в этом языке, ещё вроде нигде не описана (потому что она идиотская)
это практическая проверка гипотезы Снаута, что любое чисто-функциональное I/O строится на скрытии неких данных от кого-то
поскольку в чистая функция всегда возвращает одно и то же для одинаковых входных данных, для описания I/O используют некий дополнительный параметр (зачастую фиктивный) в котором, якобы, хранится состояние всего мира (io в Mercury, RealWorld в Haskell)
т.е. получили на вход реальный мир (q), сделали с ним что-то (распечатали строку на экран), и вернули новый мир (q'), где строка напечатана
взяли новый мир q', где распечатана строка, запустили ракеты и получили мир q'', и т.д.
вроде всё прекрасно и чисто функционально, но ушлый юзер может после этого начать снова пользовать ссылку на мир q, скажем
это означает, что он возвращается во времени к моменту, где строка на экран ещё не напечатана и ракеты не запущены
т.е. чтобы выполнить такой код, рантайм языка должен восстановить пользователя из радиоактивного пепла и потом стереть его память
пока такого ещё не изобрели, и текущее решение состоит в том, чтобы запретить программисту трогать ссылки на старые миры
unique types просто запрещают их трогать: юзать можно, но ровно один раз, а потом низзя!!
монадки делают то же самое, но хитрее: ссылка на RealWorld просто не экспортируется из модуля, так что работать с ней может только узкий круг доверенных функций из этого модуля, которые уж точно назад во времени не путешествуют
т.е. и в том и в другом случае есть скрытие каких-то данных
в результате, программист может наплодить сколько угодно миров
стирать память мы по-прежнему не умеем, поэтому нужно снова применить скрытие
только скрывать мы будем не данные от программиста, а результат работы программы от пользователя
т.е. если запустить программу на этом языке, не произойдёт ничего, она просто повиснет
однако побочные эффекты программы можно "измерить"
например, заинтерраптив её
при "измерении" из всего множества миров остаётся один из них, и только тогда можно понять, какой именно
к примеру, есть такой псевдокод:
main(q)=
let
q' = print(q, "пидар идёт ")
f(a,b) = a -- без разницы, что делает f
in f(print(q', "нахуй"), print(q', "напитон"))
видно, что мы использовали q' дважды и получили в итоге два разных мира
при измерении побочных эффектов этой программы мы с равной верятностью получим вывод "пидар идёт нахуй" и "пидар идёт напитон"
в реальности всё чуть сложнее, поскольку мы манипулируем не просто строками, а термами языка, но это не суть
это касается вывода
ввод тоже есть (при сильном желании)
как мы помним, все миры равновероятны
но если скопировать один мир много раз (т.е. начать писать "нахуй" в бесконечном цикле), очевидно же, что чем дольше выполнять программу, тем с большей вероятностью пидар пойдёт нахуй
на этом и строится, собственно, ввод