Вопрос

Недавно я начал читать о языке программирования 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

(Предупреждение: непроверенный код)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top