2016-10-18 90 views
2

是什麼在Haskell的方式來表達類似:哈斯克爾錄音功能限制

data SinkBuilder 
    { openSink :: MonadIO m => m Sink 
    } 

data Sink = Sink 
    { writeSink :: MonadIO m => Value -> m() 
    , closeSink :: MonadIO m => m() 
    } 

我想我需要的是一組功能,它方便地在數據類型「捆綁」在一起,所以這個數據類型是創造和傳遞作爲一件事?

這似乎是組成原因是有用的,例如,我可以實現類似

(:+:) :: SinkBuilder -> SinkBuilder -> SinkBuilder 
a :+: b = SinkBuilder $ do 
    sa <- openSink a 
    sb <- openSink b 
    return $ Sink (\v -> writeSink sa >> writeSink sb) (closeSink sa >> closeSink sb) 

它不工作,因爲我不能對錄音功能的限制,但它也看起來非常難看,所以我很確定應該有一個更好的方法來做到這一點。

+1

是不是'MonadIO m => m sink'相當於'IO Sink'? – Michael

+0

@Michael我認爲他們是等價的,如果'm'被普遍量化。 – chi

+0

不是一個等價物,我有我自己的monad,它是MonadIO。 此外,我想有更多的約束,例如'(MonadIO m,MonadState MyState m)=> ...' –

回答

0

這個編譯,但我不清楚你真的想做什麼。我擔心這不是你想要的。

{-# LANGUAGE ScopedTypeVariables, RankNTypes #-} 

import Control.Monad.Trans 

type Value = Int 

data SinkBuilder = SB 
    { openSink :: forall m. MonadIO m => m Sink 
    } 

data Sink = Sink 
    { writeSink :: forall m. MonadIO m => Value -> m() 
    , closeSink :: forall m. MonadIO m => m() 
    } 

(#+#) :: SinkBuilder -> SinkBuilder -> SinkBuilder 
a #+# b = SB $ do 
    sa <- openSink a 
    sb <- openSink b 
    return $ Sink (\v -> writeSink sa v >> writeSink sb v) (closeSink sa >> closeSink sb) 
+0

謝謝,我會試試這個。 我想要的是有一個有效的'Sink'的概念:可以打開的東西,然後我可以發送一些值並關閉它。 例如,我可以將一個Sink寫入一個XML文件,一個Sink寫入一個Json文件等等。我還希望能夠以'Sink + Sink = Sink'的方式編寫它們,所以當我發送到結果接收器都寫入(或許多)文件。 這裏引入了約束,因爲某些接收器可能會以「MonadState S m =>」約束的方式「有狀態」。 我只是不知道如何更好地建模... –