2014-07-23 118 views
2

我正在爲CIS 194的作業問題工作。
我停留在Homework 5,問題6.功能類型實例

的類型類Expr用於表示表達和用於容納變量中的任何表達式的類型類HasVars
該問題要求對M.Map String Integer -> Maybe Integer實施Expr的實例,其中MData.Map

class Expr a where 
    add :: a -> a -> a 
    mul :: a -> a -> a 
    lit :: Integer -> a 

這裏是爲Expr實例Integer的代碼。

instance Expr Integer where 
    add m n = m + n 
    mul m n = m * n 
    lit m = m 

和功能的HasVars實例,

instance HasVars (M.Map String Integer -> Maybe Integer) where 
    var s = M.lookup s 

我很困惑,如何爲函數類型創建Expr實例。 如何去模式匹配或從函數中提取數值? 該類型爲a-> a -> a,所以我沒有Map來提取這些值,var來自ShowVars用於將String轉換爲上述函數。

我沒有提出解決問題的其他部分,因爲它可能包含破壞者。

回答

8

那麼,首先寫出簽名,以便清楚應該是什麼東西。爲了使其更具可讀性,

type MS2I = M.Map String Integer 
type Integer' = Maybe Integer 

然後

add :: (MS2I -> Integer') -> (MS2I -> Integer') -> (MS2I -> Integer') 

所以,你可以用

add m n = o 
where m, n, o :: MS2I -> Integer' 

所以o開始是走地圖的功能...您可以定義:

add m n = o 
where o ms2i = ... 

現在在那點你有一張地圖。你可以喂,要的參數:

add m n = o 
where o ms2i = let i1 = m ms2i 
        i2 = n ms2i 
        i1, i2 :: Integer' 
       in ...? 

其餘的應該是顯而易見的,你只需要兩個Maybe Integer合併到一個新的。 (最好使用Applicative

的樂趣和參考,這裏有一個超級濃縮版:

import Control.Arrow 
instance Expr (Kleisli Maybe MS2I Integer) where 
    add m n = arr (uncurry(+)) . (m&&&n) 
+1

在這個階段也許太先進,但如果你使用'Applicative'到'Maybe'結合s,您也可以將它用於功能部分。 'add = liftA2 $ liftA2(+)'。 –

+0

謝謝,這是有道理的。然而'lit :: Integer - > a'仍然讓我失望。我需要使用一個整數來創建函數。所以我需要創建一個地圖或添加到一個? –

+2

@dare_take'lit'可能會讓一個表達意思是不變的,所以讓它使用一個映射參數但忽略它。 –