2016-08-24 9 views
2

のために、私は[ちょうど簡単な例]のようなものを表現したい場合は:それは変数の概念がありませんので、私はHaskellの、に何をハスケル - ループ

int a = 0; 
for (int x = 0; x < n; x += 1) 
    a = 1 - a; 

すればよいですか?(おそらく間違っています:Does Haskell have variables?を参照してください)

+1

あなたは[再帰](http://learnyouahaskell.com/recursion)でこれを行うことができます。 –

+1

p.s. Haskellには変数があります。それらは手続き型言語とは異なる動作をします。 –

+0

@code-Apprentice uuuh、 'rec x a = if x Joe

答えて

5

を、あなたが手続き型言語のループを実行することになり、繰り返しはHaskellでrecursionで達成されます。この場合、ループの結果が何であるかを考えなければなりません。これは0と1の間で交互に現れる.Haskellでこれを行うにはいくつかの方法がある。片道は

alternatingList n = take n alternating0and1 
alternating0and1 = 0 : alternating1and0 
alternating1and0 = 1 : alternating0and1 
4

ループを使用する代わりに、標準ライブラリ関数および/または独自の再帰関数を組み合わせて、目的の効果を達成します。

aは、nが偶数であるかどうかによって、0または1に設定されているようです(私が正直であればかなり混乱します)。 Haskellで同じことを達成するために、あなたが書いたと思います。多くの場合、

a = 
    if even n 
    then 0 
    else 1 
7

です。いくつかのオプションがあります。

loop :: Int -> Int 
loop n = loop' n 0 
    where loop' 0 a = a 
     loop' n a = loop' (n - 1) (1 - a) 

次に、あなたが倍として再帰を言い換えることができます:まず、あなたは素朴な再帰の問題を書き換えることができます

loop :: Int -> Int 
loop n = foldr (\a _ -> 1 - a) 0 [0..n] 

それとも、forループをシミュレートするStateを使用することができます。

import Control.Monad 
import Control.Monad.State 

loop :: Int -> Int 
loop n = execState (forM_ [0..n] 
         (\_ -> modify (\a -> 1 - a))) 0 
3

別のオプション:

iterate (\a -> 1-a) 0 !! n 
-- or even 
iterate (1-) 0 !! n 

スニペットiterate (\a -> 1-a) 0は、0から始まって得られたすべての値の無限の遅延リストを生成し、関数(\a -> 1-a)を繰り返し適用します。次に!! nはn番目の要素を取ります。

完全に正直なところ、この場合、私はiterateというより厳しい定義を探して、あまりにも多くの怠惰なサンクを作りません。

2

ハスケルでは、このような問題にどのように近づくかについての他の回答がすでに説明されています。

しかし、Haskellは、STのアクションとSTRefという形式の可変変数(または参照)を持っています。それらを使用するのは普通はあまりよくありませんが、あなたが本当にしたいのであれば、あなたはHaskellで忠実に可変的な変異コードを表現することができます。

あなたのサンプルの問題を表現するのに楽しいことをしています。

(次のコードはまた、便宜上、monad-loopsパッケージからwhileM_を使用しています。)

import Control.Monad.Loops 
import Control.Monad.ST 
import Data.STRef 

-- First, we define some infix operators on STRefs, 
-- to make the following code less verbose. 

-- Assignment to refs. 
r @= x = writeSTRef r =<< x 
r += n = r @= ((n +) <$> readSTRef r) 

-- Binary operators on refs. (Mnemonic: the ? is on the side of the ref.) 
n -? r = (-) <$> pure n <*> readSTRef r 
r ?< n = (<) <$> readSTRef r <*> pure n 


-- Armed with these, we can transliterate the original example to Haskell. 
-- This declares refs a and x, mutates them, and returns the final value of a. 
foo n = do 
    a <- newSTRef 0 
    x <- newSTRef 0 
    whileM_ (x ?< n) $ do 
     x += 1 
     a @= (1 -? a) 
    readSTRef a 

-- To run it: 
main = print =<< stToIO (foo 10)