3つの構文の違いがわかりません。
where a = f (b)do a <- f (b)do let a = f (b)
それは他の2つとは異なりますが、私はどういうわけか理解していますa <- f(b)。ほとんどの場合、3つすべてを試してみました。また、ネット上のどこかで、「慣用的」であるためにのみ、ブロックごとに1つのletバインディングを使用するように努める必要があることを読みました。しかし、私は決してうまくいかないようです。
何を使用するかをどのように決定しますか?
3つの構文の違いがわかりません。
where a = f (b)do a <- f (b)do let a = f (b)それは他の2つとは異なりますが、私はどういうわけか理解していますa <- f(b)。ほとんどの場合、3つすべてを試してみました。また、ネット上のどこかで、「慣用的」であるためにのみ、ブロックごとに1つのletバインディングを使用するように努める必要があることを読みました。しかし、私は決してうまくいかないようです。
何を使用するかをどのように決定しますか?
let foo = bar in ...単に;のコンテキスト内fooとまったく同じものであると定義します。テキスト置換を使用して、inのすべての使用を置き換えて、まったく同じ結果を得ることができます。bar...foo...(bar)
where句は式に似てlet...inいますが、式ではなく関数句の最後に配置されます。例えば、
foo x
| p1 = ... y ...
| p2 = ... y ...
where
y = ...
let...inガードをif...then...elsesに変更せずにこれを書き直す方法はありません。多くの場合、句は、純粋にスタイル上の理由で句の上にwhere使用されます。let...in
バインド演算子はまったく異なるものです。doこれは、モナディック計算から値を「抽出」するために表記法で使用されます。つまり、タイプが、の場合foo、m aその後x <- foo、xタイプは。になりaます。他のすべての「バインディング」フォームは名前を定義するだけですが、計算結果をモナド内から名前にバインド<-するために使用されます。ブロック内でのみ使用できるため、結果をバインドするアクションと同じモナドでより大きな計算を構築するためにのみ使用されます。<-do
let foo = bar表記はdo便利です。あなたは書き直すことができます:
do let foo = bar
...
なので
let foo = bar
in do ...
doしかし、そのようなバインディングがたくさんあると、ブロックがどんどん深くネストされるので、それは厄介になります。
あなたが言ったアドバイスが何について話しているのかわかりません。let...inブロック内に複数の変数をうまく定義でき、
let foo = ...
bar ...
in ...
より慣用的です
let foo = ...
in let bar = ...
in ...