我最近在Haskell玩过Monads(仍然是一个相对初学者的所有这些)。我使用Identity Monad
发现了一些有趣的行为(或者至少对我有趣)。
如果我写下以下功能:
let f = \x -> Identity 2 >>= \y -> x * y
然后执行:t
我得到f :: Num b => Identity b -> Identity b
。推断x是Identity (Num b)
。我可以使用6
调用该函数,然后得到结果12
。
但是,如果我像Maybe
那样尝试相同的事情:
let g = \x -> Just 2 >>= \y -> x * y
<interactive>:2096:5: error:
• Non type-variable argument in the constraint: Num (Maybe b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
g :: forall b. Num (Maybe b) => Maybe b -> Maybe b
因此,我需要明确返回Maybe
或使用return
。所以我这样做:let g = \x -> Just 2 >>= \y -> return $ x * y
。
一切正常。然而,我想知道Identity
monad发生了什么。
首先,我尝试添加显式返回类型,如下所示:
let f = \x -> Identity 2 >>= \y -> Identity $ x * y
然后再次:t
,我得到了f :: Num b => b -> Identity b
。这是我第一次期待的。
如果推断x + y
和Identity $
包含在x
之内,那么我会怀疑它如何能够处理y
Identity
Identity 5
。所以我尝试了以下内容:
Identity 6
+ 11
,结果为Identity 5
6
+ 11
,结果再次为Maybe
然而,我会像Just 5
一样尝试相同的
Just 6
+ Just 5
6
+ <interactive>:2116:1: error:
• Non type-variable argument in the constraint: Num (Maybe a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num (Maybe a), Num a) => Maybe a
我收到以下错误:
FlexibleContexts
我尝试了<interactive>:2134:1: error:
• No instance for (Num (Maybe a0)) arising from a use of ‘it’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
,但我收到了以下错误:
Identity
我想知道是否有人可以解释为什么Maybe
monad行为与FlexibleContexts
不同?
还可以使用Maybe
来获得与protected $token;
public function __construct($token){
$this->token = $token;
$this->checkToken();
}
protected function checkToken() {
if (current_method() == "POST" || "PUT" || "PATCH") {
if (CSRF::verifyToken(@$_POST['token'])) {
$this->checkPrefix();
}
} elseif (current_method() == "GET" || "DELETE") {
if (CSRF::verifyToken($this->token)) {
$this->checkPrefix();
}
}
}
monad相同的行为吗?我还没有能够让它继续工作。
非常感谢先进。
答案 0 :(得分:3)
这是因为Identity
有Num
个实例而Maybe
没有(你可以在GHCi中使用:i
或查看{{3}来查看类型的实例}})。
因此,当您有\x -> Identity 2 >>= \y -> x * y
时,*
实际上是来自*
Num
的{{1}}个实例的Identity a
(其中a
是Num
它本身就是Int
个实例,例如Double
或5 :: Num a => a
等。
此外,Haskell中的数字文字是多态的:Num
,因此它们可以像任何Int
实例一样运行,而不是局限于特定的实例(如Double
或{{1} })。当你尝试像Identity 5 + 6
这样的事情时,就会发生这种情况。从6
开始,Num a => Identity a
被推断为类型为(+) :: Num a => a -> a -> a
。
您可以更明确地看到这一点:
ghci> :t 5
5 :: Num p => p
ghci> 5 :: Identity Int
Identity 5
ghci> 5 :: Maybe Int
<interactive>:12:1: error:
• No instance for (Num (Maybe Int)) arising from the literal ‘5’
• In the expression: 5 :: Maybe Int
In an equation for ‘it’: it = 5 :: Maybe Int