2016-11-01 9 views
2

私はハスケルを完全に新しくしています。コンストラクタ内からデータを引き出す

私はいくつかの情報層を持っています。各レイヤーは独自の方法で計算されますが、出力には型付き要素のリストだけがあります。

layer1 :: MyData -> [Element1] 
layer1 mydata = unique calculations 

layer2 :: MyData -> [Element2] 
layer2 mydata = even more unique calculations, using layer1 

layer3 :: MyData -> [Element3] 
layer3 mydata = completely genious layer of profound information 
..... 

ここでは、N個の関数をパラメータ化できないため、切り離したままにしておきます。

次に、これらのレイヤーで同様の機能を実行したいと考えています。

私のmightsは簡単な方法

transform1 :: MyData -> [Int] 
transform1 mydata = zipWith f (layer1 mydata) constList 
transform2 :: MyData -> [Int] 
transform2 mydata = zipWith f (layer2 mydata) constList 
transform3 :: MyData -> [Int] 
transform3 mydata = zipWith f (layer3 mydata) constList 
...... 

でそれを行うしかし、ここで明確には統一のいくつかの種類を作るために招待されます。 Like

universalTransform :: Layer -> [Int] 
universalTransform layer = zipWith f layer constList 

Ok。だから今、私はLayer抽象

data Layer = Lay1 [Element1] | Lay2 [Element2] | Lay3 [Element3] 
data LayerName = Lay1Name | Lay2Name | Lay3Name 

をする必要があるそれから私は

take :: LayerName -> MyData -> Layer 
take lname mydata = case lname of 
    Lay1Name -> Lay1 (layer1 mydata) 
    Lay2Name -> Lay2 (layer2 mydata) 
    Lay3Name -> Lay3 (layer3 mydata) 

派遣コレクタを作成する必要があり、何とかそれはhugerとhugerになり、最悪の問題は私のzipWith fリストを望んでいるということです。そしてuniversalTransformlayerにはではなく、のリストです。抽象化はLayerです。私はLayerの中から[ElementsX]の中から自由にしようとしていましたが、成功しませんでした。

私は間違った方向に向かっています。

どうすればいいですか?統一ですが、適切な方法で、好きではありません... ehmmm ...私自身。

+0

。なぜあなたはそれをする必要がありますか?あなたは高次関数より何を得ていますか?あなたはその道を進むことで解決しようとしている問題は何ですか? –

+0

DRYの概念。コードを統一するために、それは強く繰り返されます。レイヤーの作成は解決策ではありません。しかし私は他の道を見つけませんでした。それはハスケルの私の二日目です。たぶん私は明らかな解決策を見逃してしまったでしょう。 – Dahan

+0

@AlexisKingや他の誰かが間違っていると私を修正する気がします...あなたは要素リストの種類が異なるため、 'レイヤー'抽象化を作成するようになりました。しかし、 '(MyData - > [a]) - > MyData - > [Int]'型の 'universalTransform'を書けば、これを回避できませんか? – mnoronha

答えて

3

Alexis Kingは、Layer型を変換に要約する必要はないと指摘しています。あなたの関数は引数としてfとレイヤー関数を取るようにしてください。そうすれば、あなたは(のはconstListのタイプは[Foo]あるとしましょう)するために... ...

transform1 :: MyData -> [Int] 
transform1 mydata = zipWith f (layer1 mydata) constList 

から行く:あなたが順序を反転する場合

transform :: (a -> Foo -> Int) -> (MyData -> [a]) -> MyData -> [Int] 
transform f layer mydata = zipWith f (layer mydata) constList 

このtransformは目に容易になりますfの引数の:

transform :: (Foo -> a -> Int) -> (MyData -> [a]) -> MyData -> [Int] 
transform f layer mydata = zipWith f constList (layer mydata) 

今では明示的mydataを言及しないことが容易になる(この最後のステップは、おそらくです好みの問題は、私は好きでは最高のそれこの方法):

transform :: (Foo -> a -> Int) -> (MyData -> [a]) -> MyData -> [Int] 
transform f layer = zipWith f constList . layer 

transformと何がLayerでやって推測されたとの主な実質的な違いは、このソリューションであなただけの三つの方法に制限されていないということですLayerNameで指定されたレイヤーを作成します。しかし、あなたがあなたの問題をどのように述べているかを考えれば、まずはこのような制限が本当に必要ないと思います。


PS:あなたが実際に(再び、私は強く、あなたが実際に必要としない疑いがあるものです、)あなたのLayerの提案に似た何かを望んでいた場合、あなたはおそらく何かのように、より良い運を持っているでしょう...

あなたが zipWithを与える

toLayer :: LayerName -> MyData -> [Element] 

機能になります。

data Element = Elem1 Element1 | Elem2 Element2 | Elem3 Element3 

...プラス層生成機能(実際にリストを生成すること!)その後、Element上ケース分析を行うための責任がある:あなたが「だから今、私は `Layer`の抽象化を行う必要がある」と述べたまで、私はあなたと一緒にいた

f :: Foo -> Element -> Int 
+1

はい、ありがとうございます!私は元気です。それは私に、機能的なものがハスケルの定義において実際に何を意味するのかを理解するのに時間がかかりました。私は時々ルビー/レールでラムダを使って楽しい時間を過ごしていますが、ちょっとです。ここでは、Haskellの関数はすべて周囲にあります。それらは他の関数への引数として渡されています。それは気が変わります。それは最初のことを見るのをやめ、プロセスを見始めるようなものです。 OOP/ruby​​では私は何かを持っていて、何ができるのか考えていました。ハスケルでは、私は関数を持っていて、それを何に適用するかを考える。 – Dahan

+0

@AlexeySkoblikov "これは最初のことを見るのを止め、プロセスを見始めるようなものです。 - それは精神だ。あなたのコメントの文脈では、例えば 'g'と' layer79'を適切な型で定義すれば、 'transform g layer79'はまったく普通の' MyData - > [Int] '関数です'MyData - > [Int]'引数を受け付ける他の関数の引数を含め、どこでも使用できます。 – duplode

関連する問題