11

私はこれを読みました:

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

私はアイデアが好きです、拡張機能を使いたいです。ただし、1 つのことを確認したいと思います: ビュー関数が 1 回の一致に対して 1 回評価されるかどうかです。

だから、私たちが持っているとしましょう:

{-# LANGUAGE ViewPatterns #-}
...

f (view -> Nothing) = ...
f (view -> Just x) = ...

view :: a -> Maybe b

を呼び出すとしましょうf aview指定された引数に対して 2 回呼び出されるか、1 回だけ呼び出されますaか?

編集

私はこれが事実であるかどうかを調べようとし、次のように書きました:

{-# LANGUAGE ViewPatterns #-}

import System.IO.Unsafe

blah (ble -> Nothing) = 123
blah (ble -> Just x) = x

ble x = unsafePerformIO $ do
    putStrLn $ "Inside ble: " ++ show x
    return x

main :: IO ()
main = do
    putStrLn $ "Main: " ++ show (blah $ Just 234)

GHC を使用した出力:

Inside ble: Just 234
Inside ble: Just 234
Main: 234

GHC を使用した出力 (最適化あり)

Inside ble: Just 234
Main: 234

GHCi を使用した出力:

Main: Inside ble: Just 234
Inside ble: Just 234
234
4

1 に答える 1

13

一度だけ:

効率性: 同じビュー関数が関数定義またはケース式の複数の分岐に適用される場合 (例えば、size上記)、GHC はこれらのアプリケーションを単一のネストされたケース式にまとめて、ビュー関数のみが適用されるようにしようとします。一度。GHC でのパターンのコンパイルは、The Implementation of Functional Programming Languages のChapter 4 で説明されている行列アルゴリズムに従います。行列の最初の列の一番上の行がすべて "同じ" 式を持つビュー パターンである場合、これらのパターンは単一の入れ子になったケースに変換されます。これには、たとえば、次のように、タプルに並ぶ隣接するビュー パターンが含まれます。

f ((view -> A, p1), p2) = e1
f ((view -> B, p3), p4) = e2

2 つのビュー パターン式が「同じ」であるという現在の概念は非常に制限されています。完全な構文上の同等性でさえありません。ただし、変数、リテラル、アプリケーション、タプルは含まれます。たとえば、 の 2 つのインスタンスview ("hi", "there")が収集されます。ただし、現在の実装は alpha-equivalence まで比較されないため、 の 2 つのインスタンスは結合されません(x, view x -> y)

GHCマニュアル

スニペットに関しては、最適化を使用してコンパイルしていないことが問題です。と の両方を使用するghc -Oghc -O2、行は一度だけ印刷されます。GHCを使用しているときにパフォーマンス関連の問題が発生した場合は、常に最初に確認することです:)

(ちなみに、Debug.TraceunsafePerformIOを使用すると、手動でハックを作成しなくても、この種のことを確認できます。)

于 2012-01-20T20:15:38.347 に答える