Haskell,错误展开Maybe Int

时间:2016-01-27 19:15:59

标签: haskell

我写了代码:

is3 :: Int -> Maybe Int 
is3 x = is3temp 0 x 

is3temp :: Int -> Int -> Maybe Int 
is3temp p x = if (abs p*p*p) < (abs x) then (is3temp (p+(signum x)) x) else (if p*p*p == x then (Just p) else Nothing) 

c :: Maybe Int -> Int 
c (Just x) = 2*x+1 
c Nothing = 0

--fun::Int ->  Int
--fun = c.is3

c1:: Int -> Int
c1 x = 2*x +1
c1 0 = 0

fun::Int ->  Int
fun x = (is3 x) >>= c1

如您所见is3接受Int并返回Maybe Int。

fun中,我从is3取结果解包并尝试将其发送到c1。

并获得错误

ERROR file:1627.hs:47 - Type error in application
*** Expression     : is3 x >>= c1
*** Term           : c1
*** Type           : Int -> Int
*** Does not match : a -> b c

这里有什么问题?

2 个答案:

答案 0 :(得分:2)

让我们检查is3 x >>= c1

中汇总的所有类型
x            :: Int
is3          :: Int -> Maybe Int 
c1           ::                      Int ->   Int
                                     |||     /???\
is3 x        ::        Maybe Int     |||    ???????
(>>=)        ::        Maybe a   -> (a   -> Maybe b) -> Maybe b
(>>=) is3 x  ::                     (Int -> Maybe b) -> Maybe b
is3 x >>= c1 ::                                         $!%&/#?

正如您所看到的,c1不能作为>>=的右侧,因为它的返回类型是错误的。它必须返回某种Maybe。可以使用return . c1

轻松解决此问题
return . c1  :: Int -> Maybe Int

fmap,因为monad法律规定两者必须具有相同的效果:

fmap c1         :: Maybe Int -> Maybe Int
fmap c1 (is3 x) ::              Maybe Int

但是,这也会改变fun的类型。话虽这么说,你的函数名称相当糟糕,c1可能是一个错字(如果fun的类型是正确的)。您实际上可能想要使用c

fun :: Int -> Int
fun x = c (is3 x)

答案 1 :(得分:1)

编译的一些代码:

is3 :: Int -> Maybe Int
is3 x = is3temp 0 x

is3temp :: Int -> Int -> Maybe Int
is3temp p x = if (abs p*p*p) < (abs x) then (is3temp (p+(signum x)) x) else (if p*p*p == x then (Just p) else Nothing)

c1 :: Int -> Int
c1 0 = 0
c1 x = 2*x +1

fun :: Int -> Maybe Int
fun = (fmap c1) . is3

我将fun的类型从Int -> Int更改为Int -> Maybe Int,并使用fmap代替>>=

我还在c1中翻了匹配的顺序。匹配从上到下应用,因此0案例永远不会按照您拥有的顺序应用。