2016-08-18 5 views
4

私はIOの文脈におけるいくつかのデータ型を持っているように:私のような一つのデータオブジェクトで一緒にそれらをすべて入れたい変容( - > b)の

a :: IO String 
b :: IO FilePath 
c :: String -> IO String 

data Configdata = Configdata String FilePath (String -> String) 

だから私はIOのコンテキストのうち、ちょうどIO Configdataのうち、自身のためにそれぞれの値を取得する必要はありません。

解決策がないクリティカルポイントは、String -> IO StringIO (String -> String)に変換する方法です。 Hoogleはこれを実行できる機能を私に与えていません。

関数の入力が無限である可能性があるため、多分それが可能でないかどうかわかりません。

誰かが解決策または説明を持っていますか? 私は、関数の代わりにリストを使うことはオプションであることを知っていますが、可能であれば関数を使うことを好むでしょう。

+14

これは実際には互換性がありません。 'String - > IO String'では、IO計算は' IO(String - > String) 'の引数に依存することができます。 – Bergi

+1

@Bergiはそれを完全に述べました。これは、ApplicativeとMonadの主な違いです。 – user2297560

答えて

10

実際これは不可能です。機能を考えてみましょう:それはIO (String -> String)にこれを変換することができれば

import Acme.Missiles 

boo :: String -> IO String 
boo "cute" = return "Who's a nice kitty?" 
boo "evil" = launchMissiles >> return "HTML tags lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain" 

、それは純粋なString -> String機能を返す前all possible IO actions for any inputを実行する必要があります。 IOWは、たとえあなたが子猫を見る目的のためだけに機能を使うことを計画していたとしても、核兵器の虐殺を伴います。

しかし、あなたの特定のアプリケーションにはを実行することができます。特に、関数があらかじめ定義された文字列に対してのみ呼び出されることがわかっている場合は、IOから事前にクエリを実行し、その結果をマップに格納して、純粋にインデックスを作成することができます。

import qualified Data.Map as Map 

puh :: IO (String -> String) 
puh = fmap ((Map.!) . Map.fromList) . forM ["cute"] $ \q -> do 
     res <- boo q 
     return (q, res) 

もちろん、これはパフォーマンス上の理由では実現できません。

+2

文字列があらかじめ用意されている場合は、文字列ごとに1つの値を持つ小さなカスタムタイプを作成するのが適切でしょう。次に、宇宙パッケージはあなたに '' sequenceA ::(Foo - > IO String) - > IO(Foo - > String) '](http://hackage.haskell.org/package/universe-1.0/docs/Data)を与えることができます。 -Universe-Instances-Reverse.html#t:Traversable)、これは 'Map'を作成し、その中にインデックスを付けるという振る舞いを持っています。 –

関連する問題