

Haskell初心者です。  
質問なのですが、

[code]

    parseDnsMessage :: BG.BitGet DnsMessage
    
    recQuery :: BS.ByteString -> String -> IO BS.ByteString
    
    
    resolveName :: [Word8] -> [Word8] -> BS.ByteString -> String
    resolveName qname name bstr = do
      let newbstr = BSL.toStrict $ replace (BS.pack qname) (BS.pack name) bstr
      retbstr <- recQuery newbstr (head rootServers4)
      let msg = BG.runBitGet retbstr parseDnsMessage
      case msg of
        Right m -> (intercalate "." $ map show (rdata $ head $ answer $ m))
    
[/code]

\---以下エラーメッセージ---

[code]

    Couldn't match expected type ‘[BSI.ByteString]’
                with actual type ‘IO BSI.ByteString’
    In a stmt of a 'do' block:
      retbstr <- recQuery newbstr (head rootServers4)
    In the expression:
      do { let newbstr
                 = BSL.toStrict $ replace (BS.pack qname) (BS.pack name) bstr;
           retbstr <- recQuery newbstr (head rootServers4);
           let msg = BG.runBitGet retbstr parseDnsMessage;
           case msg of {
             Right m
               -> (intercalate "." $ map show (rdata $ head $ answer $ m)) } }
    
[/code]

このような場合どのように書くのが適切なのでしょうか？  
よろしくお願いします。


CC BY-SA 3.0
2016-02-29T14:33:45.160
22671
2016-02-29T17:48:42.337
14603
question
haskell
HaskellのIOアクションの取り扱いについて


do 記法は、 `<-` によって中身を取り出しながら処理ができているように見えますが、制約があって、その do
記法全体が表す値は、中身を取り出されるモナドの型でなくてはいけません。

別の言葉で言うと、 IO の中身を `<-` で取り出して何かしらを記述する場合には、その結果も IO でないといけません。

なので、少なくとも resolveName は

[code]

    resolveName :: [Word8] -> [Word8] -> BS.ByteString -> IO String
    
[/code]

であるべきです。これを実現するのに、必要とされている関数は、 `String -> IO String`を実現する関数になるかと思います。これのためには、
[`return`](http://hackage.haskell.org/package/base-4.8.2.0/docs/Prelude.html#v:return)
が使えます。

最後の `intercalate` の戻り値を return に食わせて、正しそうな形へ変形していくと、欲しい物が得られるのではないでしょうか。


CC BY-SA 3.0
2016-02-29T17:00:15.330
22675
2016-02-29T17:07:47.007
2016-02-29T17:07:47.007
754
754
22671
answer