Używam Reactive-Banana w interfejsie WX. Po naciśnięciu przycisku muszę pobrać wartość z zewnętrznego interfejsu API usługi.Reactive Banana: jak używać wartości ze zdalnego interfejsu API i scalać je w strumieniu zdarzeń
Mam rodzajowy Behavior
w oparciu o typ danych AppState
, który "akumuluje" transformowane zmiany na podstawie transformacji funkcji (doSomeTransformation
). Wartości przekształcane są transportowane przez zdarzenia i pochodzą ze zdalnego interfejsu API (getRemoteValue
) po naciśnięciu przycisku na interfejsie. Pisałem szczupłą wersję kodu, który reprezentuje zasadniczy element:
module Main where
{-# LANGUAGE ScopedTypeVariables #-} -- allows "forall t. Moment t"
import Graphics.UI.WX hiding (Event)
import Reactive.Banana
import Reactive.Banana.WX
{-----------------------------------------------------------------------------
Main
------------------------------------------------------------------------------}
data AppState = AppState {
count :: Int
} deriving (Show)
type String = [Char]
main :: IO()
main = start $ do
f <- frame [text := "AppState"]
myButton <- button f [text := "Go"]
output <- staticText f []
set f [layout := margin 10 $
column 5 [widget myButton, widget output]]
let networkDescription :: forall t. Frameworks t => Moment t()
networkDescription = do
ebt <- event0 myButton command
remoteValueB <- fromPoll getRemoteApiValue
myRemoteValue <- changes remoteValueB
let
doSomeTransformation :: AppState -> AppState
doSomeTransformation ast = ast { count = count ast }
coreOfTheApp :: Behavior t AppState
coreOfTheApp = accumB initialState $ (doSomeTransformation to combine with myRemoteValue) <$ ebt
sink output [text :== show <$> coreOfTheApp]
network <- compile networkDescription
actuate network
getRemoteApiValue :: IO Int
getRemoteApiValue = return 5
i Cabal conf:
name: brg
version: 0.1.0.0
synopsis: sample frp gui
-- description:
license: PublicDomain
license-file: LICENSE
author: me
maintainer: [email protected]
-- copyright:
category: fun
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable bgr
main-is: Main.hs
-- other-modules:
-- other-extensions:
build-depends: base >=4.7 && <4.8
, text
, wx ==0.92.0.0
, wxcore ==0.92.0.0
, transformers-base
, reactive-banana >=0.9 && <0.10
, reactive-banana-wx ==0.9.0.2
hs-source-dirs: src
default-language: Haskell2010
ghc-options: -Wall -O2
Mój problem polega na tym, jak komponować doSomeTransformation
i myRemoteValue
w taki sposób, że mogę użyj zdalnej wartości API jako normalnej wartości zdarzenia. changes
z banana-reaktywnego ma następujący podpis:
changes :: Frameworks t => Behavior t a -> Moment t (Event t (Future a))
który będzie zawijać moja IO Int
z getRemoteApiValue
.
Więc w zasadzie jak mogę iść z:
IO Int -> Moment t (Event t (Future AppState)) -> AppState
?
BTW Nie jestem pewien, czy jest czystszy o tej innej funkcji podpis: doSomeTransformation :: Int -> AppState -> AppState
, gdzie wartość Int
jest reprezentowana przez zwracaną wartość API. To brzmi jak dwa Behavior
s i jeden strumień. Może zły sposób na rozwiązanie problemu?
Co powiesz na samodzielne odtworzenie problemu? być może projekt FP Complete, lub przynajmniej pełny własny kod źródłowy. –
Jedną z rzeczy, które staram się zrozumieć o Haskell i fp w ogóle, jest to, że czasami wystarczy podać sygnatury funkcji, aby opisać problem sam. W każdym razie postaram się napisać coś w fpcomplete. – Randomize
Wystarczająco dużo, aby opisać problem, to nie to samo, co wystarczająca do odtworzenia problemu z piaskownicą. –