2011-10-14 72 views
2

我正在通過「在48小時內給自己寫一個計劃解釋器」,一個練習是使用符號來編寫一個函數。這是函數:這是怎麼寫的?

parseNumber :: Parser LispVal 
parseNumber = liftM (Number . read) $ many1 digit 

我嘗試以下,但沒有奏效:

parseNumber2 :: Parser LispVal 
parseNumber2 = do digits <- many1 digit 
        return $ liftM $ (Number . read) digits 

沒關係。我錯誤地縮進了代碼

+0

類型liftM'的'是'(單子米)=>(a→b)→ma→mb。在這種情況下,'liftM'是'Parser' monad中的'fmap'。但是'(Number。read)digits'不是一個monadic值,所以你遇到了一個類型錯誤(原因之一:'(Number。read)digits'不是一個函數,而是被用作函數;原因二: '(Number。read)digits'不是一個monadic值,所以它對於某個monad'm'沒有'ma'類型)。然而,在不使用'liftM'的情況下使用'return(Number(read(digits)))'是一個monadic值,並且等同於(放在最後一行時)原始定義。 – danportin

回答

6

解壓縮後的digits不再需要liftM了。所以它只是:

return $ Number $ read digits 
4

我跳上了#haskell IRC頻道,問lambdabot:

11:25 < dmwit> ?src liftM 
11:25 < lambdabot> liftM f m1 = do { x1 <- m1; return (f x1) } 
11:27 < dmwit> ?src ($) 
11:27 < lambdabot> f $ x = f x 

(如果你不想問lambdabot,你也可以要求Hoogle並單擊源。鏈接的文檔中)

所以,讓我們填寫fm1

liftM (Number . read) $ many1 digit 
    ={definition of ($)} 
liftM (Number . read) (many1 digit) 
    ={definition of liftM} 
do { x1 <- (many1 digit); return ((Number . read) x1) } 
    ={expand to layout form, eliminate redundant parentheses} 
do 
    x1 <- many1 digit 
    return ((Number . read) x1) 

你可以寫的這半打的變化不同的語法審美的,但這裏是我最喜歡的,擴大的(.)($)幾次定義之後:

={definitions of (.) and ($)} 
do 
    x1 <- many1 digit 
    return . Number . read $ x1 
+0

得愛Lambdabot。 <3 –