Как я могу подражать каналам Go с Haskell?
Вопрос
Недавно я начал читать о языке программирования GO, и я нашел переменные канала очень привлекательной концепцией. Можно ли подражать той же концепции в Хаскелле? Может быть, иметь тип данных Channel a
и структура монада, чтобы включить изменяемое состояние и функции, которые работают как ключевое слово go
.
Я не очень хорош в одновременном программировании, и простой механизм прохождения канала в Хаскелле действительно облегчит мою жизнь.
РЕДАКТИРОВАТЬ
Люди просили меня прояснить, какие узоры Go я был заинтересован в переводе с Хаскеллом. Таким образом, Go имеет переменные канала, которые являются первым классом и могут быть переданы и возвращены функциями. Я могу читать и писать в эти каналы, и поэтому легко общаться между процедурами, которые могут работать одновременно. Go также имеет go
Ключевое слово, что в соответствии с языковой спецификацией инициирует выполнение функции одновременно как независимый поток и продолжает выполнять код, не ожидая.
Точный шаблон, который меня интересует, - это что -то вроде этого (синтаксис Go - это странно - переменные объявляются Varname Vartype вместо обычного перевернутого пути - но я думаю, что он читается):
func generateStep(ch chan int) {
//ch is a variable of type chan int, which is a channel that comunicate integers
for {
ch <- randomInteger() //just sends random integers in the channel
}
func filter(input, output chan int) {
state int
for {
step <- input //reads an int from the input channel
newstate := update(state, step) //update the variable with some update function
if criteria(newstate, state) {
state = newstate // if the newstate pass some criteria, accept the update
}
output <- state //pass it to the output channel
}
}
func main() {
intChan := make(chan int)
mcChan := make(chan int)
go generateStep(intChan) // execute the channels concurrently
go filter(intChan, mcChan)
for i:=0; i<numSteps; i++ {
x <- mcChan // get values from the filtered channel
accumulateStats(x) // calculate some statistics
}
printStatisticsAbout(x)
}
Мой основной заинтересован в том, чтобы сделать моделирование Монте -Карло, в котором я генерирую конфигурации последовательно, пытаясь изменить текущее состояние системы и принимая модификацию, если она удовлетворяет некоторые критерии.
Тот факт, что использование тех каналов я мог бы написать очень простой, читаемой и маленькой симуляции Монте -Карло, который был бы параллельно в моем многоядерном процессоре, действительно впечатлил меня.
Проблема в том, что у GO есть некоторые ограничения (особенно у него не хватает полиморфизма в том, как я привык в Хаскелле), и, кроме того, мне очень нравится Хаскелл, и я не хочу обменять его. Таким образом, вопрос в том, есть ли какой -то способ использовать некоторые механики, которые выглядят как код выше, чтобы легко выполнить одновременное симуляцию в Хаскелле.
Изменить (2, контекст):Меня не изучают в информатике, особенно в одновременности. Я просто парень, который создает простые программы для решения простых проблем в моей ежедневной рутине исследования в дисциплине, не связанной с CS. Я просто нахожу способ, которым Haskell работает интересным и люблю использовать его, чтобы выполнять мои маленькие обязанности.
Я никогда не слышал о одних каналах Pi-Calculus или CSP. Извините, если вопрос кажется больным, это, вероятно, моя ошибка в огромной подписке.
Вы правы, я должен быть более конкретным в том, какой шаблон в Go я хотел бы повторить в Хаскелле, и я постараюсь отредактировать вопрос, чтобы быть более конкретным. Но не ожидайте глубоких теоретических вопросов. Дело в том, что из нескольких вещей, которые я прочитал и кодировал, кажется, что у меня есть аккуратный способ сделать параллелизм (и в моем случае это просто означает, что моя работа по созданию всех моих ядер напекает с численными расчетами. Если бы я мог использовать аналогичный синтаксис в Хаскелле, я был бы рад.
Решение
Я думаю, что вы ищете Control.concurrent.chan из базы. Я не обнаружил, что это отличается от Chans Go, кроме очевидных хаскелификаций. Каналы не являются чем -то особенным, посмотрите на Вики страница об этом.
Каналы являются частью более общей концепции, называемой передача последовательных процессов (CSP), и если вы хотите сделать программирование в стиле CSP в Хаскелле, вы можете взглянуть на Сообщение процессов Haskell (CHP) упаковка.
ТЭЦ - это лишь один из способов выполнения параллелизма в Хаскелле, взгляните на Страница параллелизма Haskellwiki Чтобы получить больше информации. Я думаю, что ваш вариант использования может быть лучше написан с помощью ДАННЫЕ ПАРРАЛЛЕЛЬНЫЕ ХАСКЕЛЛ, Однако в настоящее время это работа, поэтому вы можете использовать что -то еще.
Другие советы
Расширение ответа Haskellelephant, control.concurrent.Chan - это путь к каналам и контролю. Concurrent's forkIO
может эмулировать go
ключевое слово. Чтобы сделать синтаксис немного более похожим на GO, можно использовать этот набор псевдонимов:
import Control.Concurrent (forkIO)
import Control.Concurrent.Chan (newChan, readChan, writeChan)
import Control.Concurrent.MVar (newMVar, swapMVar, readMVar)
data GoChan a = GoChan { chan :: Chan a, closed :: MVar Bool }
go :: IO () -> IO ThreadId
go = forkIO
make :: IO (GoChan a)
make = do
ch <- newChan
cl <- newMVar False
return $ GoChan ch cl
get :: GoChan a -> IO a
get ch = do
cl <- readMVar $ closed ch
if cl
then error "Can't read from closed channel!"
else readChan $ chan ch
(=->) :: a -> GoChan a -> IO ()
v =-> ch = do
cl <- readMVar $ closed ch
if cl
then error "Can't write to closed channel!"
else writeChan (chan ch) v
forRange :: GoChan a -> (a -> IO b) -> IO [b]
forRange ch func = fmap reverse $ range_ ch func []
where range_ ch func acc = do
cl <- readMVar $ closed ch
if cl
then return ()
else do
v <- get ch
func v
range_ ch func $ v : acc
close :: GoChan a -> IO ()
close ch = do
swapMVar (closed ch) True
return ()
Это можно использовать так:
import Control.Monad
generate :: GoChan Int -> IO ()
generate c = do
forM [1..100] (=-> c)
close c
process :: GoChan Int -> IO ()
process c = forRange c print
main :: IO ()
main = do
c <- make
go $ generate c
process c
(Предупреждение: непроверенный код)