2012-11-11 25 views
1

爲什麼Prog A編譯並運行正常,而Prog B編譯失敗?由於綁定/賦值運算符爲函數返回String而不是函數返回Int

PROG一個

func :: String -> String 
func a = a 

mydofn a = do 
    x <- func a 
    return x 

main = print "Finished" 

PROG乙

func :: Int -> Int 
func a = a 

mydofn a = do 
    x <- func a 
    return x 

main = print "Finished" 

PROG乙編譯錯誤:

Couldn't match expected type `m0 t0' with actual type `Int' 
In the return type of a call of `func' 
In a stmt of a 'do' block: x <- func a 
In the expression: 
    do { x <- func a; 
     return x } 
+0

你還想讓mydofn做什麼?它會澄清你的目的,也許可以幫助我們給出更多有用的答案。 – AndrewC

回答

6

用DO-符號,此代碼:

mydofn a = do 
    x <- func a 
    return x 

mydofn a = func a >>= (\x -> return x) 

現在只是語法糖,>>=具有類型Monad m => m a -> (a -> m b) -> m b,但在第二個例子中,應用func a的類型爲Int,它不能與Monad m => m a統一(因爲Int是獨立的,不在m內部),這就是類型檢查器告訴你的(「C不能匹配m aInt「)。但爲什麼在第一種情況下工作呢?

Haskell中的字符串只是字符列表([Char])。而且有a Monad instance for [a] in the standard library,看起來像這樣:

instance Monad [] where 
    m >>= k    = foldr ((++) . k) [] m 
    return x   = [x] 

所以[Char]獲取與Monad m => m a(與m = []a = Char)和你的第一個例子統一成爲

mydofn a = foldr ((++) . (\x -> [x])) [] (func a) 

或等價

mydofn a = concat . map (\x -> [x]) $ func a 

這只是將字符串的每個字符映射到一個單獨的字符串(​​被映射到["a", "b", "c"]),然後連接所有結果字符串(["a", "b", "c"]變成​​)。

4

在PROG A,你」重新使用列表單子,因爲String = [Char]。 沒有Int monad! 在PROG A,

mydofn a = do 
    x <- func a 
    return x 

相當於

mydofn a = [x | x <- func a] 

所以它實際上只是在列表中,不改變任何東西的要素運行。

在PROG A,m0 t0匹配[] Char,你可以不寫Int作爲m0 t0所以這就是爲什麼你得到了與前衛B.錯誤


mydofn相當於

mydofn a = do 
    func a 

相當於mydofn a = func a,意思與mydofn a = a相同。

我認爲這是爲了澄清問題而減少的例子。你還想用mydofn做什麼?

也許你的意思

mydofn a = do 
    x <- return (func a) 
    return x 

這將讓它與詮釋工作,但我仍然不知道你的目的是什麼。