2012-05-24 80 views
3

可以做任何事情來爲未定義的值定義Show實例嗎?也許有一些GHC擴展存在?我想是這樣的:a顯示未定義的實例

> print (1,undefined) 

(1,"undefined") 
+8

您只能爲_types_創建實例。 'undefined'是一個_value_,它沒有特別的類型,它只是Bottom--它可以有任何類型。 – leftaroundabout

+0

我同意@leftaroundabout,我沒有看到實現這一目標的可能性。 –

+2

你的用例是什麼?如果你的意思是捕捉異常,那可以完成,但不應該在Show實例中完成。 –

回答

4

按照Haskell 2010 report, chapter 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" 

由於打印值包括評價它,這總是會給出一個錯誤。

+1

然而,傳遞給'print'並不一定要評估它,這取決於'Show'實例 – newacct

0

即使(如別人已經指出的那樣),你不能爲undefined指定Show例如,您可以通過使用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" 

它不會像

呼叫工作
+0

我不知道爲什麼,但GHCI的'+ t'選項告訴'showCatch 1'有String類型,但它實際上是'IO String'。我將它固定在答案中。 –

2

底部值(其中undefined是一種風味)是一個永遠不會構建的值,因此無法觀察到。這意味着你無法打印它。這個值不能與其他語言的null進行比較,通常可以觀察到,甚至檢查。

undefined以及error "blah"和其他所有底部等效爲無限循環的結果很有用。無限循環的結果從來沒有構建過,因此無法觀察。

+0

理論上這是真的,但實際上我正在打印它,看到我的答案:) –

+0

很好的回答,歡迎來到SO! – Ashe

1

更概念上:「未定義」不是像'X'這樣的值。 'X'值的類型爲Char。 「undefined」有哪些類型?符號「未定義」是多態的,它可以有任何類型(任何類型*)。

類型類,如類型t中的「顯示t」調度。所以不同的類型可以有不同的顯示功能。哪個函數得到你的「未定義」取決於類型。

在GHCI中,大多數多態類型默認爲(),因此它可以運行該命令。一個可以使顯示功能的一個新類型,不看價值:

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。