2016-04-05 17 views
4

doブロックでスコープがどのように機能するのかを理解しようとしています。私は次のコードをお持ちの場合haskellモナドでスコープを理解する

は:

l = [1, 2, 3] 
m = [1, 2] 

を、これは

res = do 
    a <- l 
    b <- m 
    return (a, b) 

罰金作品やmlのデカルト積を返します。私は別の形でこれを書き換えるしようとした範囲を理解することが

(ブロックを行うことなく、)

私はそれを「unsugar」とthisを使用してしようとしたので、ブロックはモナドの操作上だけ糖衣構文ですかということを知っていますこれを思いついた:

res = l >>= (\a -> m) >>= (\b -> return (a, b)) 

奇妙なことに、このエラーはNot in scope: ‘a’です。

doブロック内のreturnがアクセスできる魔法のように見えるので、どこが間違っているのか、おそらくどのようにスコープが機能するのか教えていただけますか?

は問題があなたのコード内のラムダの範囲がかなり右ではないということです非常に

答えて

12

、ありがとうございました。それは、小さな計算の周りだけでなく、表現の終わりに至るまで拡張する必要があります。あなたのコードはdesugarにする必要があります

l >>= (\a -> m >>= (\b -> return (a, b)) 

ちょっと削除することができます、少し楽しいです。

l >>= \a -> m >>= \b -> return (a, b) 

しかし、この種の意味がわかりにくい。あなたは痛いほど明白なようにしたい場合は、我々は接頭表記に変換し、おそらく糖が助けオペレータの一部を剥ぎ取る

bind a f = a >>= f 
bind l (\a -> bind m (\b -> return (a, b)) 

言うことができます。

どのように>> =のネストの中にラムダ、その周りではありません。これにより、aが有効範囲内に残るようになります。実際には、この入れ子は、手書きで書く苦痛の少しです。それはドロー記法の原動力の一部です:)

+0

私は申し訳ありませんが、2つの良い答えがあり、これは最初でした。 私は今理解しています。今はすべての異なるラムダがあるので、なぜこのコードについて私が混乱したのかが分かるので、すべて意味があります。 ありがとうございます(お二人とも) –

7

問題はあなたのかっこでです。あなたは

res = l >>= (\a -> m) >>= (\b -> return (a, b)) 

を書くが、何が必要なのも、あなたが途中でaを結合ラムダ式を終了し、その後、aを使用しようとした

res = l >>= \a -> m >>= \b -> return (a, b) 

を書き込むことができます

res = l >>= (\a -> m >>= (\b -> return (a, b))) 

です。

関連する問題