haskell 中的可为空列表参数

cre*_*dd1 3 haskell

我是 Haskell 的新手,我试图实现一个接受“null”参数的 head 函数版本

\n
safeHead :: Maybe [a] -> Maybe b\nsafeHead (Just []) = Nothing\nsafeHead Nothing = Nothing\nsafeHead (Just (x:xs)) = Just x\n
Run Code Online (Sandbox Code Playgroud)\n

从概念上讲,它对我来说看起来不错。但类型系统不接受最新的方程。\n为什么?

\n
    \xe2\x80\xa2 Couldn\'t match expected type \xe2\x80\x98b\xe2\x80\x99 with actual type \xe2\x80\x98a\xe2\x80\x99\n      \xe2\x80\x98a\xe2\x80\x99 is a rigid type variable bound by\n        the type signature for:\n          safeHead :: forall a b. Maybe [a] -> Maybe b\n        at ch04.hs:2:1-32\n      \xe2\x80\x98b\xe2\x80\x99 is a rigid type variable bound by\n        the type signature for:\n          safeHead :: forall a b. Maybe [a] -> Maybe b\n        at ch04.hs:2:1-32\n    \xe2\x80\xa2 In the first argument of \xe2\x80\x98Just\xe2\x80\x99, namely \xe2\x80\x98x\xe2\x80\x99\n      In the expression: Just x\n      In an equation for \xe2\x80\x98safeHead\xe2\x80\x99: safeHead (Just (x : xs)) = Just x\n    \xe2\x80\xa2 Relevant bindings include\n        xs :: [a] (bound at ch04.hs:4:19)\n        x :: a (bound at ch04.hs:4:17)\n        safeHead :: Maybe [a] -> Maybe b (bound at ch04.hs:3:1)\n\n
Run Code Online (Sandbox Code Playgroud)\n

chi*_*chi 6

在类型签名中输入像a和这样的变量b

safeHead :: Maybe [a] -> Maybe b
Run Code Online (Sandbox Code Playgroud)

由函数调用者选择。这意味着,如果有人调用您的函数,他们可以选择使用它,就好像它是一样

safeHead :: Maybe [String] -> Maybe Int
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用者对您的第三个方程不满意

safeHead (Just (x:xs)) = Just x
Run Code Online (Sandbox Code Playgroud)

因为x有 a ,而不是类型签名所暗示的Stringan 。Int

为了修复代码,我们需要削弱我们的类型承诺:该函数不会返回Maybe ball b,而仅返回b = a。因此,我们需要使用

safeHead :: Maybe [a] -> Maybe a
                            -- ^ --
Run Code Online (Sandbox Code Playgroud)

最后,请注意,通常这种“安全头”函数是用 type 定义的[a] -> Maybe a。我想知道是否Maybe真的需要额外的输入。额外的东西并没有什么问题Maybe——但它可能不是你真正需要的。

  • @creatldd1creatldd1 实际上,链接“A -> Maybe B”形式的函数通常是最方便的。“Maybe”的“Monad”(和“Applicative”)实例使得使用“>>=”、“<=<”等运算符组合这些函数变得非常容易;当您在链中间的某个阶段得到“Nothing”时,这些运算符本身将负责处理,短路并确保链中的其余函数永远不会被调用。这样你就可以将函数编写为实际接收值;他们只关心自己的“失败”,而不关心上游的“失败”。 (3认同)