Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
{-# LANGUAGE ExistentialQuantification,
DeriveDataTypeable,
PatternSignatures #-}
import Data.Typeable
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.Chan
-- Core data types
data Message = forall t . Typeable t => Message t | StopMessage
deriving Typeable
data Handler = forall t . Typeable t => Handler (t -> IO ())
-- Worker thread
data Worker = Worker (Chan Message) (MVar ())
workerThread :: [Handler] -> Chan Message -> MVar () -> IO ()
workerThread handlers chan finish = loop where
loop = do
message <- readChan chan
case message of
StopMessage -> putMVar finish ()
Message val -> do
foldr (tryHandler val) (putStrLn "Unhandled message") handlers
loop
tryHandler val (Handler h) rest = maybe rest h (cast val)
startWorker :: [Handler] -> IO Worker
startWorker handlers = do
chan <- newChan
finish <- newEmptyMVar
forkIO (workerThread handlers chan finish)
return $ Worker chan finish
send :: Typeable m => Worker -> m -> IO ()
send (Worker chan _) message = do
writeChan chan $ Message message
stopWorker :: Worker -> IO ()
stopWorker (Worker chan finish) = do
writeChan chan $ StopMessage
takeMVar finish
-- Some tests
data Test = Test Bool String deriving Typeable
intHandler :: Int -> IO ()
intHandler val = putStrLn $ "Int: " ++ show (val * 2)
strHandler :: String -> IO ()
strHandler val = putStrLn $ "String: " ++ reverse val
testHandler :: Test -> IO ()
testHandler (Test b s) = putStrLn $ "Test: " ++ show b ++ " " ++ show s
main = do
w <- startWorker [
Handler intHandler,
Handler (\(val::Char) -> putStrLn $ "Char: " ++ show val),
Handler strHandler,
Handler testHandler]
send w (5::Int)
send w False
send w 'a'
send w "foo"
send w (Test True "bar")
stopWorker w
putStrLn "Finished!"
Вот такая вот портянка была написана под влиянием дискуссии с HaskellGovno http://govnokod.ru/11968, и недавней его просьбой рассказать об общении потоков в хаскеле.
Код запускает тред, в который можно передавать различные сообщения (ограничение только одно - тип сообщения должен быть инстансом тайпкласса Typeable). В треде исполняются указанные хендлеры, каждый из которых ловит свой тип сообщений.
>портянка была написана под влиянием HaskellGovno
Очень красиво. 🙂 Декларативно. А как этот паттерн называется? Планировщик на основе статически типизированных сообщений?
Не отнаследованы от Typeable, а принадлежат Typeable. Если мне не изменяет память, оверхед там только при использовании типов данных с forall, в остальных случаях компилятору и так все ясно.
Это ты написал какой-то конвейер с нелимитированной очередью-списком, которая типа канал.
А хендлеры - это вновь изобретенный полиморфизм или же мультиметоды, если хотите.
>StopMessage -> putMVar finish ()
А без отравленных сообщений никак нельзя? Недолюбливаю я эти пилюли.
Ничего сверхгодного в вашем бомжественном хацкиле нету, я такую же хреновину в императивном стиле напишу за 15 минут с библиотечной очередью.
> Да как-то некошерно в очереди с данными передавать управляющие конвеером сообщения.
> volatile boolean terminated=false;
Так с этим булом потом начинаются проблемы - надо одновременно опрашивать и бул и очередь. Как это сделать в хаскеле - я х.з.
Имхо даже в императивном языке проще кинуть особое сообщение для остановки треда, чем городить этот огород с булом и его опросом.
>надо одновременно опрашивать и бул и очередь. Как это сделать в хаскеле - я х.з.
Отож. И я об этом.
>даже в императивном языке проще кинуть особое сообщение для остановки треда
Если потребителей много - не проще. Или надо делать одного потребителя и тредпул, которому он раздает задания.
Конечно если других средств коммуникации помимо канала нету - то символ "Конец передачи" неизбежен.
PS. Херня какая-то с говнокодом. Сессии на главной нету, а на остальных есть.
> Если потребителей много - не проще.
Как вариант - если у нас N воркеров - вбросить N сообщений об остановке. Каждый получит ровно по одному. Минус способа - надо знать сколько именно запущено воркеров.
>Как вариант - если у нас N воркеров - вбросить N сообщений об остановке.
Ну ведь потому и костыль. В данном случае оно вылазит наружу во всей красе.
Говно всплывает к верху, так сказать.
Переменная, а зачастую какой-то енум с состояниями INIT,RUN,STOP,FAIL гораздо лучше.
Как-то раз, в одном из трамваев я увидел надпись "давайте уедем жить в Питер", выцарапанную на спинке кресла каким-то отчаянным романтиком. Наверно, это был тарас Б.
>Ничего сверхгодного в вашем бомжественном хацкиле нету, я такую же хреновину в императивном стиле напишу за 15 минут
Я расскажу тебе свою историю.
Я учился в университете, по специальности программист. Да, я не был в группе самым одарённым, но я пытался что-то делать. Нам преподавали C++. Я не очень это всё понимал. Мои одногруппники были не очень хорошими людьми, и всегда не воспринимали меня и даже ущемляли. Преподы тоже не упускали своего и говорили, что только тупые не могут понять C++. Я не был тупой, я просто не понимал зачем всё это нужно?
Однажды я шёл по городу, ел шаурму, думая как бы им всем доказать, что я круче их.
И вдруг я услышал разговор двух молодых парней, которые выходили из новой машины, они говорили про программирование. Они были классно одеты. У них было много денег. Я хотел быть ими. Я подошёл к ним и спросил:
— Как мне стать таким как Вы?
Они улыбнулись и сказали: “Пошли с нами”.
Мы зашли в ближайшее кафе, один из них достал ноутбук и показал его — Haskell. Я по-настоящему понял. Я влюбился. Я был счастлив. Я пошёл домой, я прочитал haskellwiki, я накачал книг с amazon.com, я начал читать. Да я уже не ходил на занятия, мне они были уже не нужны. Потом мне позвонили из деканата и сказали, что отчислят меня, если я не сдам курсовую. Мне было наплевать, что меня отчислят, но курсовой, я его сдам, ведь у меня есть новое знание.
Когда я пришёл на защиту, то там собралась вся группа.
Они подходили к компьютерам и демонстрировали применение паттернов и шаблонов, наследование и прочее, всё что на самом деле не нужно.
Потом настала моя очередь. Я встал и медленно шёл. Они смеялись и кричали — что не написал видать?
Когда я показал этот код, который делал одной строчкой то, что у них было в 25 классах, они замолчали. Я встал и ушёл.
Говорят препод ушёл с работы из-за того, что свихнулся, он не мог поверить что его C++ не нужен.
Я теперь иногда телефоны своих одногруппников в газете объявлений, где они готовы работать за еду. Но мне пофиг, я знаю Haskell, что приносит мне тысячи долларов.
1. Когда вижу портянку в полтора экрана - сразу ясно что это не твой текст.
2. Тухло, ведь я уже читал эту пасту.
3. Она неуместна - в примере 50 строк потрачено на конвейер.
> 1. Когда вижу портянку в полтора экрана - сразу ясно что это не твой текст.
+
> 2. Тухло, ведь я уже читал эту пасту.
+
> 3. Она неуместна - в примере 50 строк потрачено на конвейер.
Ну не на сам конвейер, в качестве которого тут использовался готовый Chan, а на тред, который этот конвейер использует.
я поступил в универ. там было все: и матан, и жаба, и паскакаль, и сци и сци-крест-крест, и васик, и алгоритмы и структуры данных, и опенжл, и даже философия, психология и физкультура.
и мне это все было интересно и сложно, но я не стал золотомедалистом по одной причине: еще на первом курсе нам преподавали самые основы поцкаля. на первую же лабу я постарался:
слабал на трубопоцкале игрулю тетрис, со всеми наворотами: и режим 320х200х256 и ассмовставки, и графоэффекты типа шторок и затемнения, и уровни, и спецфигуры - полный блекджек. и даже шлюхи были после каждого пройденного уровня. не было только музыки по причине отсутствия колонок.
я был глуп и наивен, с широко открытыми глазами, полными желания постигать и творить круть несусветную. но жизнь меня обломала, и я стал учиться из рук вон плохо, так и не окончив: препод покивал головой, позыркал на шлюх, и сказал:
- это все очень хорошо, но для нашей программы этого всего не нужно.
У меня нубский вопрос: А вот на Хокаге.хаскел.орг или на каких-то других сайах с документацией часто упоминается какие-то правила laws. Что это означает и как это выражается в коде Хаскеля? Почему для этого отдельный термин используют laws (законы)?
Кстати, запиши, пожалуйста, функцию :: (Double, Double) -> (Double, Double) -> Double, вычисляющую расстояние между двумя точками на плоскости по классической формуле так, чтобы в записи тела функции не было скобок, кроме, возможно, скобок, превращающих инфиксные функции в префиксные.
Это на степике такая задача есть? Специальная олимпиада объявляется открытой?
import Data.STRef
import Control.Monad.ST
import Data.Complex
-- Level: Beginner
-- Well, there are no parantheses...
dist1 x y = let dx = fst x - fst y; dy = snd x - snd y in sqrt $ dx^2 + dy^2
-- Level: Math geek
-- Ha, I know complex numbers
dist2 x y = magnitude $ uncurry (:+) x - uncurry (:+) y
-- Level: Former imperative programmer
dist3 x y = runST $ do
ref <- newSTRef $ (^2) $ fst x - fst y
modifySTRef ref $ (+) $ (^2) $ snd x - snd y
sqrt <$> readSTRef ref
P.S. придумал забавный способ сконвертировать пару в список, но не придумал, как его красиво использовать на двух парах, чтобы заюзать sqrt . sum . map (^2) . zipWith (-)
:t uncurry (:) . fmap pure
uncurry (:) . fmap pure :: (a, a) -> [a]
Очень красиво. 🙂 Декларативно. А как этот паттерн называется? Планировщик на основе статически типизированных сообщений?
А хендлеры - это вновь изобретенный полиморфизм или же мультиметоды, если хотите.
>StopMessage -> putMVar finish ()
А без отравленных сообщений никак нельзя? Недолюбливаю я эти пилюли.
Ничего сверхгодного в вашем бомжественном хацкиле нету, я такую же хреновину в императивном стиле напишу за 15 минут с библиотечной очередью.
Они самые. В том же лиспе это нативно работает.
> А без отравленных сообщений никак нельзя? Недолюбливаю я эти пилюли.
Поясните плиз, что не так со StopMessage?
> я такую же хреновину в императивном стиле напишу за 15 минут с библиотечной очередью
Да я не спорю ;). На питоне всяко и за 5 можно управиться.
Да как-то некошерно в очереди с данными передавать управляющие конвеером сообщения.
> volatile boolean terminated=false;
Так с этим булом потом начинаются проблемы - надо одновременно опрашивать и бул и очередь. Как это сделать в хаскеле - я х.з.
Имхо даже в императивном языке проще кинуть особое сообщение для остановки треда, чем городить этот огород с булом и его опросом.
Отож. И я об этом.
>даже в императивном языке проще кинуть особое сообщение для остановки треда
Если потребителей много - не проще. Или надо делать одного потребителя и тредпул, которому он раздает задания.
Конечно если других средств коммуникации помимо канала нету - то символ "Конец передачи" неизбежен.
PS. Херня какая-то с говнокодом. Сессии на главной нету, а на остальных есть.
Как вариант - если у нас N воркеров - вбросить N сообщений об остановке. Каждый получит ровно по одному. Минус способа - надо знать сколько именно запущено воркеров.
Ну ведь потому и костыль. В данном случае оно вылазит наружу во всей красе.
Говно всплывает к верху, так сказать.
Переменная, а зачастую какой-то енум с состояниями INIT,RUN,STOP,FAIL гораздо лучше.
- Баттхед, ты слышал, он сказал: "прибор!".
- А еще он сказал "канал"! Гы-гы-гы.
тогда непонятно в чем крутота хацкила, если всё то же, но только хуёвей.
Он по идее должен сам как-то всё асспараллелить и предоставить какую-то сверхудобную реализацию producer-consumer отношений.
Я расскажу тебе свою историю.
Я учился в университете, по специальности программист. Да, я не был в группе самым одарённым, но я пытался что-то делать. Нам преподавали C++. Я не очень это всё понимал. Мои одногруппники были не очень хорошими людьми, и всегда не воспринимали меня и даже ущемляли. Преподы тоже не упускали своего и говорили, что только тупые не могут понять C++. Я не был тупой, я просто не понимал зачем всё это нужно?
Однажды я шёл по городу, ел шаурму, думая как бы им всем доказать, что я круче их.
И вдруг я услышал разговор двух молодых парней, которые выходили из новой машины, они говорили про программирование. Они были классно одеты. У них было много денег. Я хотел быть ими. Я подошёл к ним и спросил:
— Как мне стать таким как Вы?
Они улыбнулись и сказали: “Пошли с нами”.
Когда я пришёл на защиту, то там собралась вся группа.
Они подходили к компьютерам и демонстрировали применение паттернов и шаблонов, наследование и прочее, всё что на самом деле не нужно.
Потом настала моя очередь. Я встал и медленно шёл. Они смеялись и кричали — что не написал видать?
Когда я показал этот код, который делал одной строчкой то, что у них было в 25 классах, они замолчали. Я встал и ушёл.
Говорят препод ушёл с работы из-за того, что свихнулся, он не мог поверить что его C++ не нужен.
Я теперь иногда телефоны своих одногруппников в газете объявлений, где они готовы работать за еду. Но мне пофиг, я знаю Haskell, что приносит мне тысячи долларов.
2. Тухло, ведь я уже читал эту пасту.
3. Она неуместна - в примере 50 строк потрачено на конвейер.
+
> 2. Тухло, ведь я уже читал эту пасту.
+
> 3. Она неуместна - в примере 50 строк потрачено на конвейер.
Ну не на сам конвейер, в качестве которого тут использовался готовый Chan, а на тред, который этот конвейер использует.
я поступил в универ. там было все: и матан, и жаба, и паскакаль, и сци и сци-крест-крест, и васик, и алгоритмы и структуры данных, и опенжл, и даже философия, психология и физкультура.
и мне это все было интересно и сложно, но я не стал золотомедалистом по одной причине: еще на первом курсе нам преподавали самые основы поцкаля. на первую же лабу я постарался:
слабал на трубопоцкале игрулю тетрис, со всеми наворотами: и режим 320х200х256 и ассмовставки, и графоэффекты типа шторок и затемнения, и уровни, и спецфигуры - полный блекджек. и даже шлюхи были после каждого пройденного уровня. не было только музыки по причине отсутствия колонок.
я был глуп и наивен, с широко открытыми глазами, полными желания постигать и творить круть несусветную. но жизнь меня обломала, и я стал учиться из рук вон плохо, так и не окончив: препод покивал головой, позыркал на шлюх, и сказал:
- это все очень хорошо, но для нашей программы этого всего не нужно.
Даже на нашем.
Спасибо. 🙂