3

我坚持使用haskell类型。

{-# LANGUAGE OverloadedStrings #-}

module Main (
    main
) where

import qualified Facebook as FB
import Network.HTTP.Conduit (withManager)
import Control.Monad.IO.Class (liftIO)
import System.IO

app :: FB.Credentials
app = FB.Credentials "localhost" "249348058430770" "..."

url :: FB.RedirectUrl
url = "http://localhost/fb"

perms :: [FB.Permission]
perms = ["user_about_me", "email"]

main :: IO ()
main = do
    fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
    liftIO $ print fbAuthUrl
    argument <- readLn
    token <- FB.getUserAccessTokenStep2 url [argument]
    withManager $ \manager -> do
        FB.runFacebookT app manager $ do
            u <- FB.getUser "me" [] token
            liftIO $ print (FB.userEmail u)

错误

src/Main.hs:23:18:
    Couldn't match expected type `IO t0'
                with actual type `FB.FacebookT
                                    FB.Auth m0 text-0.11.2.0:Data.Text.Internal.Text'
    In the return type of a call of `FB.getUserAccessTokenStep1'
    In a stmt of a 'do' block:
      fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
    In the expression:
      do { fbAuthUrl <- FB.getUserAccessTokenStep1 url perms;
           liftIO $ print fbAuthUrl;
           argument <- readLn;
           token <- FB.getUserAccessTokenStep2 url [argument];
           .... }

http://hackage.haskell.org/package/fb

4

1 回答 1

2

首先,让我以我从未真正使用过 Facebook API 或Conduits库的免责声明作为这个答案的序言,所以我不确定这段代码是否真的做了任何明智的事情,但只使用类型信息,我认为这是你想要做的

main :: IO ()
main = withManager $ \manager -> FB.runFacebookT app manager $ do
    fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
    liftIO $ print fbAuthUrl
    argument <- liftIO $ readLn
    token <- FB.getUserAccessTokenStep2 url [argument]
    u <- FB.getUser "me" [] (Just token)
    liftIO $ print (FB.userEmail u)

主要的缺陷是main在 Haskell 中必须始终具有 type IO a,但您试图使用 type 的值FacebookT Auth m ()作为您的main. 您的实现是在正确的轨道上,但runFacebookTandwithManager需要成为函数中的第一件事。

就类型而言,实际的 do-block 具有 type FacebookT Auth (ResourceT IO) ()。该runFacebookT函数用于解开FacebookT转换器,产生一个ResourceT IO ()值,然后由它处理withManager以产生一个普通的 old IO ()

另一个问题是您最初readLn在 do-block 中没有liftIO,这会混淆类型推断。我还在通话中添加了缺失JustFB.getUser内容。

于 2012-07-22T09:29:47.043 回答