2016-03-25 9 views
2

私はサーバント0.5でのREST APIの単純な例構築したい:私はそれが原因で別の場所で「期待されるタイプと一致しませんでした」たくさんのエラーのコンパイルすることはできませんサーバントの休憩APIの簡単な例、または「モナドを正しく混合する方法」?

data MyData = MyData { var1 :: Int, var2 :: String } 

app :: Application 
app = serve api server 

api :: Proxy API 
api = Proxy 

server :: Server API 
server = getItems 

getItems :: EitherT ServantErr IO [MyData] 
getItems = runEitherT $ do 
    aa <- nextRandom -- IO 
    bb <- getCurrentTime -- IO 
    cc <- getDataFromDb -- IO 

    --noteT ??? How??? 
    --MaybeT ??? How??? 

    return $ Just [MyData 111 222] 


startApp :: IO() 
startApp = run 8080 app 

を。私は "getItems"に2つの異なるモナドを混ぜているからだと思います。しかし、それだけではありません。ここで

+0

これはおそらく[this](http://haskell-servant.github.io/posts/2016-03-19-servant-0.5-release.html#switch-from-eithert-to-exceptt) 。 –

+0

エラーを再現するのに十分なコードがここにありません( 'API'型が完全に欠落しています)。 'getItems'が何をすべきかを実際に伝えるのに十分な情報はありません。しかし、一見すると 'runEitherT'は必要なく、' EitherT ... '型の値を生成しているので、実行する必要はありません。 'IO x '型の値は' liftIO'でラップする必要があります: 'aa < - liftIO nextRandom'です。 – user2407038

答えて

4

ExceptT ServantErr IO [MyData]からIO (Either ServantErr [MyData]ために何が起こっているかrunExceptT

getItems :: ExceptT ServantErr IO [MyData] 
getItems = runExceptT $ do 

。これにより、ExceptT newtypeが削除されます。しかし、あなたは他の方法をしたい!

liftIOを使用すると、IO aのアクションをExceptT ServantErr IO aアクションに持ち込むことができます。基本的には、ExceptTラッパーに「IOアクションの結果を成功コンテキストに入れる」と伝えています。

あなたの全体のdoブロックはIOに住んでいるように見えるので、あなただけ書くことができます:

getItems :: ExceptT ServantErr IO [MyData] 
getItems = liftIO $ do 
    aa <- nextRandom -- IO 
    bb <- getCurrentTime -- IO 
    cc <- getDataFromDb -- IO 
    ... 

代わりの個別IOアクションを持ち上げるを。

他の一般的な例:あなたは純粋なEitherを持っている場合は

これらの機能はすべて非常に簡単で、ソースコードを見ると参考になります。

+0

純粋な関数を公開するにはどうすればよいですか?私はそれがmyFunc :: String-> Stringを持っているとしましょう? – elviejo79

+1

@elviejo 'return'は、モナドの文脈に純粋な値を置くことを可能にします。つまり、引数が1つの純粋なハンドラを持っていれば、 'return'でそれを構成してください。 – danidiaz

関連する問題