Начиная с предыдущего вопроса здесь: Reactive Banana: как использовать значения из удаленного API и объединять их в потоке событий
Теперь у меня немного другая проблема: как я могу использовать вывод Behaviour
в качестве ввода для операции ввода-вывода и, наконец, отобразить результат операции ввода-вывода?
Ниже приведен код из предыдущего ответа, измененный вторым выходом:
import System.Random
type RemoteValue = Int
-- generate a random value within [0, 10)
getRemoteApiValue :: IO RemoteValue
getRemoteApiValue = (`mod` 10) <$> randomIO
getAnotherRemoteApiValue :: AppState -> IO RemoteValue
getAnotherRemoteApiValue state = (`mod` 10) <$> randomIO + count state
data AppState = AppState { count :: Int } deriving Show
transformState :: RemoteValue -> AppState -> AppState
transformState v (AppState x) = AppState $ x + v
main :: IO ()
main = start $ do
f <- frame [text := "AppState"]
myButton <- button f [text := "Go"]
output <- staticText f []
output2 <- staticText f []
set f [layout := minsize (sz 300 200)
$ margin 10
$ column 5 [widget myButton, widget output, widget output2]]
let networkDescription :: forall t. Frameworks t => Moment t ()
networkDescription = do
ebt <- event0 myButton command
remoteValueB <- fromPoll getRemoteApiValue
myRemoteValue <- changes remoteValueB
let
events = transformState <$> remoteValueB <@ ebt
coreOfTheApp :: Behavior t AppState
coreOfTheApp = accumB (AppState 0) events
sink output [text :== show <$> coreOfTheApp]
sink output2 [text :== show <$> reactimate ( getAnotherRemoteApiValue <@> coreOfTheApp)]
network <- compile networkDescription
actuate network
Как видите, я пытаюсь использовать новое состояние приложения -> getAnotherRemoteApiValue
-> show. Но это не работает.
Реально ли это сделать?
ОБНОВЛЕНИЕ На основе приведенных ниже ответов Эрика Аллика и Генриха Апфельмуса у меня есть текущая ситуация с кодом - это работает :):
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import System.Random
import Graphics.UI.WX hiding (Event, newEvent)
import Reactive.Banana
import Reactive.Banana.WX
data AppState = AppState { count :: Int } deriving Show
initialState :: AppState
initialState = AppState 0
transformState :: RemoteValue -> AppState -> AppState
transformState v (AppState x) = AppState $ x + v
type RemoteValue = Int
main :: IO ()
main = start $ do
f <- frame [text := "AppState"]
myButton <- button f [text := "Go"]
output1 <- staticText f []
output2 <- staticText f []
set f [layout := minsize (sz 300 200)
$ margin 10
$ column 5 [widget myButton, widget output1, widget output2]]
let networkDescription :: forall t. Frameworks t => Moment t ()
networkDescription = do
ebt <- event0 myButton command
remoteValue1B <- fromPoll getRemoteApiValue
let remoteValue1E = remoteValue1B <@ ebt
appStateE = accumE initialState $ transformState <$> remoteValue1E
appStateB = stepper initialState appStateE
mapIO' :: (a -> IO b) -> Event t a -> Moment t (Event t b)
mapIO' ioFunc e1 = do
(e2, handler) <- newEvent
reactimate $ (\a -> ioFunc a >>= handler) <$> e1
return e2
remoteValue2E <- mapIO' getAnotherRemoteApiValue appStateE
let remoteValue2B = stepper Nothing $ Just <$> remoteValue2E
sink output1 [text :== show <$> appStateB]
sink output2 [text :== show <$> remoteValue2B]
network <- compile networkDescription
actuate network
getRemoteApiValue :: IO RemoteValue
getRemoteApiValue = do
putStrLn "getRemoteApiValue"
(`mod` 10) <$> randomIO
getAnotherRemoteApiValue :: AppState -> IO RemoteValue
getAnotherRemoteApiValue state = do
putStrLn $ "getAnotherRemoteApiValue: state = " ++ show state
return $ count state
brew install ghc
или чем-то еще? у тебя есть доморощенный? если нет, подумайте о том, чтобы попробовать. вы далеко не уйдете, если у вас не установлен Haskell... Кроме того, я рекомендую использовать Stackage/stack
поверх необработанного Hackage/cabal
, и поэтому Haskell Platform не рекомендуется, потому что Stackage/stack
не рекомендует его . Просто используйте Homebrew GHC или позвольте Stack установить собственную локальную версию (версии) GHC, или и то, и другое. - person Erik Kaplun   schedule 03.10.2015mapIO
с общим типом, то естьmapIO :: (a -> IO b) -> Event t a -> Moment t (Event t b)
, как в исходном примере Генриха, что лучше, чем ваша текущая мономорфная подпись. (также я исправил ошибку в вашем коде, где вы вызываетеmapIO
— кажется, вы до сих пор не разобрались с проблемой Haskell+El Capitan :) - person Erik Kaplun   schedule 05.10.2015catch
. Если вы обновите stack.yaml rbwx, чтобы использовать версию 0.2.3 cabal-macosx, ошибка исчезнет, но вы должны сначала изменить файл cabal c-macosx, чтобы использовать правильный fgl. Но похоже, что проект cabal-macosx мертв, поэтому сначала нужно его скомпилировать. - person Randomize   schedule 05.10.2015putStrLn
s. - person Erik Kaplun   schedule 08.10.2015