2016-10-10 4 views
0

私はちょうどハスケルの学習を始めました。そして、その中にループとローカル変数があるようなハスケルのようなプログラムを書く方法を理解していません。どのようにそのようなプログラムがHaskellをどのように見えるかを誰もが示唆できますか?ローカル変数を含むので、2番目のサイクルを置き換える方法は? Haskellでコードを記述するハスケルループとローカル変数

#include <iostream> 
using namespace std; 

int main() { 

int n; 
int a [100]; 
cin >> n; 

for (int i = 0; i < n; i ++) { 
    cin >> a[i]; 
} 

int max = 0; 
int index = -1; 

for (int i = 0; i < n - 1; i ++) { 
    if (a[i+1] - a[i] > max) { 
     max = a[i+1] + a[i]; 
     index = i; 
    } 
} 

cout << index << endl; 

return 0; 

} 

私の試み:

module MyProgram where 

import Data.List 
import Data.Ord 

-- Getting a new modernized list 

f :: Int a => [a] -> [a] 
f x = zipWith (-) (tail x) (x) 

は今、私はちょうどリストを実行して、最大の要素を見つけて、そのインデックスを格納する必要があります。私はCとJavaでそれを行う方法を理解し、上の例を与えました。私はどのように実装しましたか?しかし、サイクルがないので、Haskellではです。再帰が必要ですか?

私の主な難しさは、私がハスケルのどのデザインを私の中のサイクル変数で置き換えることができるのか理解できないという事実にあります。私はインターネット上の情報を探していましたが、わかりやすいものは見つかりませんでした。

+0

ハスケルの試行を表示できますか?あなたが試したことを理解すれば、人々はあなたをより良く助けることができます。 – Sibi

+0

もちろん、コード – alex

+0

Int a => [a] - > [a] 'は無効です。あなたが「Integral a =>」または「Ord a =>」を意味していたと思います。 – ThreeFx

答えて

2

まず、要素間の相違点の一覧を取得する必要があります。さんがあなたの試みを見てみましょう:私たちは、再帰を使用した場合

f x = zipWith (-) (tail x) x 

は今、私たちはこのように、それを定義することができます。

findMax :: [Int] -> Int 
findMax list = helper 0 -1 minusInfinity $ zipWith (-) (tail list) list 
    where 
    helper _   maxIndex _   []   = maxIndex 
    helper currentIndex maxIndex currentMax (elem:list) 
     | elem > currentMax = helper (currentIndex + 1) currentIndex elem list 
     | otherwise = helper (currentIndex + 1) maxIndex currentMax list 
    minusInfinity = minBound :: Int -- the smallest element possible 

しかし、何とか再帰はかなり醜いと冗長です。

fが適切な減算リストを生成しているかどうかを見てみましょう。

これで、各要素をインデックスに関連付けることにしました。 Haskellでは、情報がzipを使用して、タプル(Int, Int)で簡単に行うことができます組み合わせること:あなたが考慮したい

zip [0..] list = [(0, 1st element), (1, 2nd element), ..] 

要素がsndでアクセスでき、今タプルの右側の部分である:

snd (index, elem) == elem 

使い方機能maximumByは、我々は今取得:

g x = maximumBy (comparing snd) $ zip [0..] $ f x 

maximumBy (comparing snd)手段「メートルを取得します各要素タプルの部分はcomparingによってsndになります。これで、(index, element)タプルが返されます。ここでは、elementが最大です。タプルの最初の要素にアクセスするために、我々は使用することができます。上記の再帰式より方法よりエレガントである

f x = fst $ maximumBy (comparing snd) $ zip [0..] $ zipWith (-) (tail x) x 

fst (index, element) == index 

だから全体の機能がのように記述することができます。

import Data.List 

calc :: (Integral a) => [a] -> a 
calc = snd . foldl (\(max,index) (x,y) -> if (y-x) > max then (y+x,index) else (max,index + 1)) (0,-1) . helper 

helper :: [a] -> [(a,a)] 
helper x = zip (tail x) (init x) 

helperは、要素の連続したペアのリストを構築:

0

は、ここでそれを行うための別の方法です。次に、calcは、あなたの命令的ループから比較や他の操作を行います。アキュムレータはローカル変数maxindexからなるタプルです。最後にインデックスが必要なだけなので、その部分を取得するにはsndを使用します。入力をタプルとして表現することで、作業を簡単にすることができます。

Demo