Haskell 与'有关的问题;刚性类型变量';在哈斯克尔的一间单间里

Haskell 与'有关的问题;刚性类型变量';在哈斯克尔的一间单间里,haskell,monads,Haskell,Monads,我正在努力更好地学习单子,并在哈斯克尔玩单子。我是这样定义单子的: module TESTMonad where import Control.Monad newtype TEST i = TEST {getTEST :: ((i, Int), Int)} deriving (Show, Eq, Ord) instance Functor TEST where fmap f (TEST ((x,y), z)) = TEST ((f x, y), z) instance Appli

我正在努力更好地学习单子,并在哈斯克尔玩单子。我是这样定义单子的:

module TESTMonad where

import Control.Monad

newtype TEST i = TEST {getTEST :: ((i, Int), Int)} deriving (Show, Eq, Ord)

instance Functor TEST where
    fmap f (TEST ((x,y), z)) = TEST ((f x, y), z)

instance Applicative TEST where
    pure = return
    tf <*> tx = tf >>= \f -> tx >>= \x -> return (f x)

instance Monad TEST where
    return x = TEST ((x, 1), 1)
    (TEST ((x, y), z)) >>= f = TEST ((plusOne a, b), c)
        where
                ((a, b), c) = getTEST (f x)

plusOne :: Int -> Int
plusOne x = x+1

我清楚地知道我可能以错误的方式做了很多事情,但我不知道它们是什么。如有任何意见,将不胜感激。提前谢谢你

无法约束
Monad
实例。
(>>=)
的类型必须为

Monad m => m a -> (a -> m b) -> m b
但是您的定义使用
plusOne::Int->Int
,使类型

Monad m => m Int -> (Int -> m Int) -> m Int
您可以安全地将
plusOne
应用于
TEST
中包装的任何其他值,因为它们已经定义为
Int
s


(>>=)
的定义不知道
x
的类型可能是什么,调用方可以选择
f
,因此它也不知道
f x
的类型可能是什么。因此,除了按原样使用它,您无法真正使用它。

是什么让您认为实现中的
a
必须是
Int
plusOne
仅将
Int
作为参数。换句话说,您的
Monad
实例必须与任何类型一起工作,但您的定义使用
plusOne
,这要求它必须是
Int
。即使将它放松到
plusOne::Num a=>a->a
对您的
Monad
实例来说仍然是太严格了。@Robin Zigmond True,但是如果我希望它是“Int”呢?在这种情况下,我应该如何定义monad测试并键入“testi”?@chepner是的,我以前试过,但没有成功。如果我希望monad只接受“Int”并使其类型更具体一点,我该怎么办;您所描述的不是a
Monad
。但是这种类型与Applicative is```````()中的````类型不同:f(a->b)->f a->f b````!注意,其中一个是
纯id v==v
。这意味着您必须保留右侧参数的“上下文”。换句话说,
TEST((f,u),)TEST((x,y),z)=TEST((fx,y,z)
。结合
pure x=TEST((x,1,1)
,我认为这构成了一个有效的
Applicative
实例;我将把它作为一个练习来验证这个定义是否满足其他三个条件。
Monad m => m Int -> (Int -> m Int) -> m Int