3

未定義の値に対して Show インスタンスを定義するために何かできることはありますか? たぶんいくつかのGHC拡張機能が存在しますか? 私はこのようなものが欲しい:

> print (1,undefined)

(1,"undefined")
4

4 に答える 4

4

Haskell 2010 レポートの第 9 章によると、評価undefinedは常にエラーを引き起こすはずです。

-- It is expected that compilers will recognize this and insert error
-- messages that are more appropriate to the context in which undefined
-- appears.
undefined :: a
undefined = error "Prelude.undefined"

値の出力には値の評価が含まれるため、これは常にエラーになります。

于 2012-05-24T13:59:24.080 に答える
2

一番下の値 (そのうちのundefined1 つのフレーバー) は、構築されていないため観測できない値です。これは、印刷もできないことを意味します。この値を他の言語と比較することはできませんnull。通常、この値は観察でき、照合することもできます。

無限ループの結果と同じように、他のすべてのボトムとundefined同様に考えると便利です。error "blah"無限ループの結果は構築されないため、観察できません。

于 2012-05-24T15:13:51.757 に答える
1

より概念的には、「未定義」は「X」のような値ではありません。'X' 値の型は Char です。「未定義」にはどのようなタイプがありますか? シンボル「未定義」はポリモーフィックであり、任意の型 (任意の種類の *) を持つことができます。

「Show t」のような型クラスは、型 t でディスパッチします。したがって、タイプが異なれば、それらを表示する別の show 関数を持つことができます。どの関数が「未定義」になるかは、タイプによって異なります。

GHCI では、ほとんどのポリモーフィック型が () にデフォルト設定されているため、コマンドを実行できます。値を見ない新しいタイプの show 関数を作成できます。

Prelude> data Test = Test
Prelude> instance Show Test where show x = "I did not look at x"
Prelude> show Test
"I did not look at x"
Prelude> show (undefined :: Test)
"I did not look at x"

しかし、ご覧のとおり、値をまったく調べないことで、未定義のエラーが回避されます。なのでこれはちょっと無理。

IO で実行され、エラーをキャッチし、必要なことを実行する独自の型クラスと印刷機械を作成できます。

import Control.Exception
perr s = do x <- try (evaluate (show s)) :: IO (Either SomeException  String)
            return (either show id x))

上記は、エラーをエラーの文字列形式に変換します。

Prelude Control.Exception> perr True
"True"
Prelude Control.Exception> perr (undefined :: Bool)
"Prelude.undefined"

注: より優れた「perr」では、WHNF だけでなく文字列全体を強制する必要があります。

于 2012-05-24T17:21:51.793 に答える
0

(他の人が既に指摘したように) のShowインスタンスを指定することはできませんが、次のコードで as をundefined使用して回避策をまとめることができる場合があります。catch

import qualified Control.Exception as C
import System.IO.Unsafe (unsafePerformIO)

showCatch :: (Show a) => a -> IO String
showCatch = showCatch' "undefined"

showCatch' :: (Show a) => String -> a -> IO String
showCatch' undef x = C.catch (C.evaluate (show x)) showUndefined
  where
    showUndefined :: C.ErrorCall -> IO String
    showUndefined _ = return undef

unsafeShowCatch :: (Show a) => a -> String
unsafeShowCatch x = unsafePerformIO (showCatch x)

ただし、この例は単純な式に対してのみ機能します。

*Main> let v1 = showCatch 1
v1 :: IO String
*Main> let v2 = showCatch $ if True then undefined else 0
v2 :: IO String
*Main> v1
"1"
*Main> v2
"undefined"
*Main> let v3 = unsafeShowCatch 1
v3 :: String
*Main> let v4 = unsafeShowCatch $ undefined
v4 :: String
*Main> v3
"1"
*Main> v4
"undefined"

次のような呼び出しでは機能しません

showCatch (1,undefined)
于 2012-05-24T14:36:02.113 に答える