從我的previous question,我一直在試圖找出一些單子代碼。首先,這裏是我使用一個狀態機功能:Haskell「無法推論」,「非類型變量參數」
import Control.Monad
import Control.Monad.Error
newtype FSM m = FSM { unFSM :: String -> m (String, FSM m) }
fsm f [] = return []
fsm f (r:rs) = do
(xs, f') <- unFSM f r
liftM (xs:) (fsm f' rs)
現在,這個編譯罰款:
exclaim :: (Monad m) => FSM m
exclaim = FSM exclaim'
exclaim' xs = return (xs ++ "!", exclaim)
但是,這確實是因爲該類型聲明不是:
question :: (MonadError String m) => FSM m
question = FSM question'
question' xs
| last xs == '?' = throwError "Already a question"
| otherwise = return (xs ++ "?", question)
錯誤是Non type-variable argument
,我認爲這是MonadError
後面的String
。如果我刪除了類型聲明,則代替Could not deduce
。我明白啓用FlexibleContexts只是「修復」這個,但是有沒有更簡單的方法可以讓我拋出錯誤?我寧願不啓用各種編譯器擴展。
Full code here。
'FlexibleContexts'是一個非常無害的擴展。沒必要害怕這一點。如果沒有類型簽名,它還會編譯您是否禁用單態限制。 – 2013-03-19 17:06:14
如果不需要擴展,只是對擴展有點不利。我寧願尋找替代方法,例如重構代碼。解決方案1是FlexibleContexts。還有其他建議嗎? – me2 2013-03-19 17:51:09
或多或少,你要得到的所有解決方案都將是「打開FlexibleContexts」。不要害怕擴展,他們會幫助你。而這一個並不神祕。這是專門讓你做你想做的。沒有更多,沒有更多。 – Carl 2013-03-19 18:05:24