2016-03-22 19 views
4

は、以下のコードを検討:haskellの多型関数のリスト?

t1 :: [Int] -> (Int,String) 
t1 xs = (sum xs,show $ length xs) 

t2 :: [Int] -> (Int,String) 
t2 xs = (length xs, (\x -> '?') <$> xs) 

t3 :: [Int] -> (Char,String) 
t3 (x:xs) = ('Y',"1+" ++ (show $ length xs)) 
t3 []  = ('N',"empty") 

をこれら三つの機能は、部分的にのみ変化するタイプを持っている - 彼らが生産する組の第一の成分の種類を知らなくても、完全に使用可能です。機能の3つのすべてがfnListToStrsの引数として独立して動作し、

fnListToStrs vs fs = (\x -> snd $ x vs) <$> fs 

GHCiの中にこれらの定義をロードし、実際に私はリストを渡すことができます。これは私がそのタイプを参照することなく、それらを操作できることを意味します

*Imprec> fnListToStrs [1,2] [t1,t2] 
["2","??"] 
*Imprec> fnListToStrs [1,2] [t3] 
["1+1"] 
:タイプの発散が行われる演算に実際に無関係であっても、私は同時にすべての3を通過することができない

*Imprec> fnListToStrs [1,2] [t1,t2] 
["2","??"] 
*Imprec> fnListToStrs [1,2] [t3] 
["1+1"] 

:しかし、彼らは同じ型を持っているので、T1とT2の両方を含みます

私はこの作品を作ることは実存またはimpredicativeのいずれかのタイプとは何かを持っているが、私はつまり、fnListToStrsを取ることができることを期待型宣言を使用するときにどちらの拡張子が私のために働いていることを感じてい:

fnListToStrs :: [Int] -> [forall a.[Int]->(a,String)] -> [String] 

これを行うには別の方法がありますか?

答えて

3

存在は正当であり、批判的ではありません。そして、Haskellは、明示的なラッパーを通して除くexistentials、...

{-# LANGUAGE GADTs #-} 

data SomeFstRes x z where 
    SFR :: (x -> (y,z)) -> SomeFstRes x z 

> fmap (\(SFR f) -> snd $ f [1,2]) [SFR t1, SFR t2, SFR t3] 
["2","??","1+1"] 

を持っていませんが、これは本当に少し無用です。

> fmap ($[1,2]) [snd . t1, snd . t2, snd . t3] 
["2","??","1+1"] 
+0

それは私が物事を少し単純化しまし可能です:あなたはおそらく、とにかく最初の結果では何もできないので、それだけで、すぐにそれを捨てると、単純な単形のリストに残っている機能を入れて、より賢明です私の質問は、実際にこれをどのように適用するかわかりません。実際のシナリオでは、関数はすでに型でラップされていますが、両方の型がパラメータとして型に公開されています。私は事実上、パラメータの1つを無視してリストを作成する必要があります。単純化されたAPIを作成しようとしているので、クライアントは明示的なラッパーを使用する必要はありません。しかし、それは可能ではないかもしれないようです... – Jules

3

これらの機能をリストに入れるには、何らかの方法でそれぞれを「ラップする」必要があります。最も簡単なラッピングは、(特に実存タイプで)これらをラップするために、確かに、他の方法はただ

wrap :: (a -> (b, c)) -> a -> c 
wrap f = snd . f 

ありますされていますが、それらのいずれかがあなたに少しでも良いだろうことを示唆する情報を与えられていませんでしたアプリケーションは、この最も単純なバージョンよりも優れています。

ここでは、さらに洗練されたものが意味をなさない場合の例を示します。あなたは

data Blob a b = Blob [a -> b] [a] 

があると今、あなたはすべて同じbタイプを持っているが、異なるa型を持つことがタイプBlob a bの値のリストを作りたいと想像。それが今、あなたはリストを作成し、適用する機能(複数可)の決定を延期することができます

data WrapBlob b where 
    WrapBlob :: Blob a b -> WrapBlob b 

を書くために理にかなってので、実際には各引数に各関数を適用することは、潜在的な結果の法外大きなリストにつながる可能性禁止価格を払うことなく、どの議論に結びつくのか。