類型安全可以說,我已經得到了下面的代碼哈斯克爾:與邏輯上不同的布爾值
type IsTall = Bool
type IsAlive = Bool
is_short_alive_person is_tall is_alive = (not is_tall) && is_alive
說,後來,我有以下
a :: IsAlive
a = False
b :: IsTall
b = True
,並調用以下,圍繞錯誤的方式得到兩個參數:
is_short_alive_person a b
這成功地編譯不幸,並在運行時高死亡人員而不是短暫的活着的人。
我想上面的例子不編譯。
我第一次嘗試是:
newtype IsAlive = IsAlive Bool
newtype IsTall = IsTall Bool
但我不能這樣做。
switch_height :: IsTall -> IsTall
switch_height h = not h
作爲not
上沒有IsTall
S,只Bool
已定義。
我可以一直明確地提取Bool
,但這在很大程度上破壞了目的。
基本上,我想IsTall
s到與其他IsTall
小號互動,就像他們Bool
S,只是它們不會Bool
S和IsAlive
•不用顯式轉換交互。
實現這一目標的最佳方法是什麼?
p.s.我想我已經做在GHC與數字實現這一點:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype UserID = UserID Int deriving (Eq, Ord, Num)
newtype GroupID = GroupID Int deriving (Eq, Ord, Num)
(即用戶名的和羣ID的不應該交互)
,但我似乎不能與Bool
S(派生BOOL要做到這一點不起作用)。無論如何,我甚至不確定以上是最好的方法。
你想要的'IsTall'和'IsAlive'類型是一個可怕的想法。這是使用不相交類型來確保類型安全的一般體面思想的錯誤概括。將它與你的'UserID'和'GroupID'進行比較;在這種情況下,具有獨立的類型是有意義的,因爲將'UserId'傳遞到需要'GroupID'的地方是沒有意義的,或者將一個添加到另一個(儘管可能都不應該實現「Num」)。然而,測試一個人是否高大*和*活着,高*還是*活着,*不高*和*活着等等是有意義的。 –
sacundim:在很大程度上,我改變了我的想法到這一點視圖。我最終使用了'newtype Height = Tall | Short「然後做'x == Tall'等。稍微輸入一點,但我認爲它使得代碼更具可讀性和類型安全性。 – Clinton