理解Haskell中为什么可能存在类型签名的困难

理解Haskell中为什么可能存在类型签名的困难,haskell,types,maybe,type-signature,Haskell,Types,Maybe,Type Signature,嗨,我很难理解我的函数需要的类型签名 -- findPassword :: Map.Map Hash Passwd -> Int -> Hash -> Maybe Passwd findPassword rTable width hashVal = do let usefulHashes = take (width+1) (iterate (pwHash.pwReduce) hashVal) let hashesInMap = [i | i <- usef

嗨,我很难理解我的函数需要的类型签名

-- findPassword :: Map.Map Hash Passwd -> Int -> Hash -> Maybe Passwd
findPassword rTable width hashVal = do
    let usefulHashes = take (width+1) (iterate (pwHash.pwReduce) hashVal)
    let hashesInMap = [i | i <- usefulHashes, Map.member i rTable]
    let goodPass = [ rTable Map.! j | j <- hashesInMap]
    let findPass = listToMaybe [ helper k hashVal width | k <- goodPass, (helper k hashVal width) /= "" ] 
    return findPass
    where
        helper :: Passwd -> Hash -> Int -> Passwd
        helper passW hashVal width
            | (pwHash passW) == hashVal   = passW
            | width == 0                  = ""
            | otherwise                   = helper (pwReduce (pwHash passW)) hashVal (width-1)

所以我的问题是为什么它期望一个Maybe(Maybe Passwd)值?如果我将类型签名切换到Maybe(Maybe Passwd),它可以工作,但是输出应该是一个double,即“Passwd”。如果我删除类型签名,它就可以正常工作。这只是项目其余部分的一个小片段,如果需要澄清,请告诉我。

Haskell不是Java。您不应该以
返回来结束一切。要让它工作,只需将
returnfindpass
更改为
findPass
。您还应该考虑删除冗余<代码> Do/<代码>块,只使用<代码> < < /C> >而不是所有的<代码> > <代码> S.< /P>请发布一个。这应该包括一个
main
函数,该函数说明如何调用该
findPassword
函数。我建议您了解何时应该使用
do
,何时不应该使用。当一个函数只是在进行计算时,你不应该使用
do
@code学徒这已经是一个最小的可重复的例子。问题是它的推断类型与签名中所需的类型不匹配,您只需要编译代码来复制它,而不是运行它。@JosephSible@Monica对于比我更了解Haskell的人来说,这里可能有足够的信息来给出合理的答案。但是,我无法重现OP()所声称的错误,因此我要求提供更多的细节,以便我可以自己玩它。@Code-pedurent啊,我明白了。OP忘记了导入,并在发布的代码中重命名了一个变量。所以这确实不是很容易复制,尽管原因与没有
main
方法无关。这很有效,谢谢,你能解释一下为什么我不能在那里使用return语句吗?@cksss Haskell中没有return语句
return
只是一个函数,没有理由期望对数据调用随机函数会有帮助。一般来说,不要依赖其他语言的经验来预测给定函数的功能,尤其是仅基于其名称。查看类型,并阅读文档以了解它的真正功能。@cksss(IMO)名称不好的
return
函数获取一个值并将其包装在
Monad
中。所以如果你给它一个
也许Int
,它会吐出一个
也许(也许Int)
或者一个
[也许Int]
,或者一个
IO(也许Int)
。在这种情况下,
return
所能给出的任何值都不是函数返回的正确内容。现在,由于
Monad
意味着
Applicative
,我建议在必要时使用
pure
(它将值包装在
Applicative
中)而不是
return
,因为语义更好。也就是说,这里既不需要
pure
也不需要
return
(实际上两者都不能使用)。
* Couldn't match type `Maybe Passwd' with `[Char]'
      Expected type: Maybe Passwd
        Actual type: Maybe (Maybe Passwd)
    * In a stmt of a 'do' block: return result
      In the expression:
        do let usefulHashes
                 = take (width + 1) (iterate (pwHash . pwReduce) hashVal)
           let hashesInMap = ...
           let goodPass = ...
           let findPass = ...
           ....
      In an equation for `findPassword':
          findPassword rTable width hashVal
            = do let usefulHashes = ...
                 let hashesInMap = ...
                 let goodPass = ...
                 ....
            where
                turntoMaybe :: [Passwd] -> Maybe Passwd
                turntoMaybe list = listToMaybe list
                helper :: Passwd -> Hash -> Int -> Passwd
                helper passW hashVal width
                  | (pwHash passW) == hashVal = passW
                  | width == 0 = ""
                  | otherwise = helper (pwReduce (pwHash passW)) hashVal (width - 1)
   |
78 |     return result