2016-09-10 6 views
4

私がHaskellについて最も気に入っていることの1つは、コンパイラが関数シグニチャのIOモナドを介して副作用をどのように見つけるかです。エスケープモナドIO

{-# LANGUAGE MagicHash #-} 

import GHC.Magic(runRW#) 
import GHC.Types(IO(..)) 

hiddenPrint ::() 
hiddenPrint = case putStrLn "Hello !" of 
    IO sideEffect -> case runRW# sideEffect of 
    _ ->() 

hiddenPrintは型ユニットであるが、それは(それがハロー印刷します)と呼ばれるときの副作用をトリガします:しかし、2つのGHCプリミティブをインポートして、このタイプのチェックを回避しやすいようです。隠されたI/Oを禁止する方法はありますか(GHCのプリミティブを誰もインポートすることを信じる以外に)?

+6

私はIOの有用性(と同様の安全機能)は、 "あなたがそれを壊したくない場合には簡単な方法ではない" 。 –

+2

また、 'System.IO.Unsafe'をインポートし、' unsafePerformIO'を使用する方が簡単です;)。バイパスは簡単ですが、安全ではありません。 – Zeta

+0

'unsafeDupablePerformIO(IO m)=(#_、a#) - > a'のrunRW#mこれはまったく同じですが、このモジュールは分かりませんでした:) simplifierのを読むときに' runRW#コア。 –

答えて

7

これはSafe Haskellの目的です。ソースファイルの先頭に{-# Safe #-}を追加すると、安全であるか、{-# Trustworthy #-}というラベルの付いたモジュールのみをインポートできます。これはまた、オーバーラップするインスタンスにいくつかの軽い制限を課します。

3

ハスケルで純度を落とす方法はたくさんあります。しかし、それらを見つけるためにあなたの道から出なければなりません。ここではいくつかある:それはunsafePerformIO

  • を使用
  • 純粋でない場合には、純粋なものとしてC関数をインポートするFFIを使用した低レベルプリミティブ
  • にアクセスするGHC内部モジュールをインポート

    • Ptr aを使用してunsafeCoerce
    • を使用して、独自のTypeableのインスタンスを宣言
    • デリファレンスポインタが有効なデータを指していない、とあなたが虐待することができるように横たわってcast。 (もはや可能最近のGHCで)危険な配列操作

    すべてのこれらの、およびその他

  • を使用して
  • は、定期的に使用することを意味しません。コンパイラに「私がしていることを知っている、私のやり方ではいられない」と伝えることができるように、彼らはそこにいます。そうすることで、あなたは自分がやっていることが安全であることを証明する証明の負担を負うことになります。

  • +1

    最近のGHCのバージョンでは、あなた自身の 'Typeable'インスタンスを定義することはできません。あなたが一番近ければ 'unsafeCoerce'に' Dict(Typeable a) 'のようなものがありますが、それはローカル効果しか持たないでしょう。 – dfeuer

    +0

    @dfeuer自動派生が実装されて以来、これはもはや不可能と思われました。説明をありがとう。 – chi