[英]Using NUnit Multiple Assert when Assert statements are in different methods
[英]Using Haskell's types to replace assert statements or if checks in other languages
抱歉,如果您的問題很基本,那么我對Haskell還是很陌生。 可以說我有一個只能使用黃金比例(1.618)中的兩個數字的函數,如何定義myfun xy的類型以僅采用黃金比例數字。 如果我從程序中調用沒有黃金分割率數字的myfun會發生什么(編譯錯誤?)? 如果在運行時通過用戶輸入進行無黃金比率編號的呼叫會發生什么情況?
您可能想要只能用黃金比率數字構造的ADT ,然后編寫myfun接受該數據類型。
我以Integer作為基本類型,但您可以使用其他類型(例如:Double或Float),甚至可以是多態的。
1)制作ADT
module Golden (Gold, getGold, buildGold) where
data Gold = G Integer Integer
getGold :: Gold -> (Integer, Integer)
getGold (G x y) = (x, y)
buildGold :: Integer -> Integer -> Maybe Gold
buildGold x y
| isGolden x y = Just (G x y)
| otherwise = Nothing
注意,此模塊導出Gold
類型,但不導出構造函數(即,不是G
)。 因此,獲取Gold
類型值的唯一方法是buildGold
,它執行運行時檢查-但只能執行一次檢查-因此,所有使用者都可以使用Gold的值並將其假定為黃金比率,而無需檢查。
2)使用ADT來建立myfun
myfun :: Gold -> ???
myfun g = expr
where (x, y) = getGold g
現在,如果您嘗試使用非黃金數字(一個非Gold
類型的值)調用myfun
,則會出現編譯時錯誤。
buildGold
要構建黃金數字,必須使用buildGold
函數,該函數強制檢查數字。
注意什么時候被檢查! 您有一個編譯時保證,始終要為myfun
和要與Gold
一起使用的所有其他函數提供黃金分割率。 程序輸入(來自用戶,網絡或其他任何地方)仍需要運行時檢查,這就是buildGold
提供的功能; 顯然,永遠不會有一個程序可以保證人類不會鍵入不想要的東西。
問題注釋中給出的替代方案也值得考慮。 如果您只需要一個函數myfun
,那么ADT可能會很繁重,否則可能失敗,然后只有myfun :: (Integer, Integer) -> Maybe ???
。
實際上,您能做的最好的事情就是運行時檢查。 可能會有一些我不知道的類型級別的演算(請參閱luqui的評論),但這在Haskell中並不實用。
您可以使用assert ,這是您要替換的,
checker :: a -> b -> Bool
checker x y = x * 1.618 `approxEqual` y
unsafeMyfun :: a -> b -> c
unsafeMyfun x y = assert (checker x y) (doRealThingWith a b)
或返回Maybe a
(或Either err a
)以避免純函數無法捕獲的異常,
myfun :: a -> b -> Maybe c
myfun x y = do
guard $ checker x y
return $ doRealThingWith x y
或使用Tom的答案等中的自定義合同類型。無論如何,都不可能在編譯時檢查約束。 實際上,由於IO monad,任何編譯時約束都無法精確確定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.