2013-07-10 161 views
1

用幾個詞來描述問題。我想我有一個算法來檢查一番,並根據算法,它可以失敗,略有不同的錯誤,例如:可擴展錯誤

data Error1 = Error1 
data Error2 = Error2 
data Error3 = Error3 

class Algorithm a where 
    type CanFailWith a :: * 
    check :: Something -> Maybe (CanFailWith a) 

instance Algorithm FirstAlgorithm where 
    type CanFailWith FirstAlgorithm = Either Error1 Error2 
    ... 

instance Algorithm SecondAlgorithm where 
    type CanFailWith SecondAlgorithm = Either Error1 (Either Error2 Error3) 
    ... 

這個選項並不是因爲難以與它合作的用戶非常友好的多枝結構,例如

testError (Left Error1)   = ... 
testError (Right (Left Error2)) = ... 
testError (Right (Right Error3)) = ... 

它看起來不錯,有三個錯誤,但它值得每一個額外的錯誤。

錯誤可能是簡單相加類型:

data Error = Error1 
      | Error2 
      | Error3 

但在這種情況下,我強迫用戶覆蓋在第一種算法是不可能的情況下,不能失敗,Error3

的問題是:有沒有任何常見和理想的簡單到最終用戶解決方案,以擴大錯誤?

+1

你可以讓'Either's稍微容易使用'TypeOperators'像'數據的處理:+:B = A:+:B'着,說,'infixr 6:+:'。現在,您可以編寫'實例算法SecondAlgorithm,其中CanFailWith SecondAlgorithm = Error1:+:Error2:+:Error3'類型。對於這種類型,可能有一種棘手的方式來製作廣義消除器函數,但我現在無法想到它。 –

+0

什麼是'testError'的類型簽名?你需要首先決定這個函數的類型 – Ankur

+0

在這個例子中它是'testError :: CanFailWith SecondAlgorithm - > ...',但它並不一定完全相同。 –

回答

2

你可以嘗試這樣的事情,每個算法有自己的錯誤總和類型。

{-# LANGUAGE TypeFamilies #-} 

class Algorithm a where 
    data CanFailWith a :: * 
    check :: a -> [Int] -> Maybe (CanFailWith a) 

data FirstAlgo = FirstAlgo deriving (Show) 

instance Algorithm FirstAlgo where 
    data CanFailWith FirstAlgo = FError1 | FError2 
    check a x = Nothing 

data SecondAlgo = SecondAlgo deriving (Show) 

instance Algorithm SecondAlgo where 
    data CanFailWith SecondAlgo = SError1 | SError2 | SError3 
    check a x = Nothing 


testError :: CanFailWith SecondAlgo ->() 
testError SError1 =() 
testError SError2 =() 
testError SError3 =()