簡體   English   中英

haskell 中 Monad 中的“剛性類型變量”問題

[英]Problem with 'rigid type variable' in a Monad in haskell

我正在嘗試更好地學習單子,並在 Haskell 中使用它。 我以這種方式定義了一個 monad:

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

但是當我嘗試編譯它時出現以下錯誤:

TESTMonad.hs:16:47: error:
    • Couldn't match expected type ‘Int’ with actual type ‘b’
      ‘b’ is a rigid type variable bound by
        the type signature for:
          (>>=) :: forall a b. TEST a -> (a -> TEST b) -> TEST b
        at TESTMonad.hs:16:24
    • In the first argument of ‘plusOne’, namely ‘a’
      In the expression: plusOne a
      In the expression: (plusOne a, b)
    • Relevant bindings include
        a :: b (bound at TESTMonad.hs:18:19)
        f :: a -> TEST b (bound at TESTMonad.hs:16:28)
        (>>=) :: TEST a -> (a -> TEST b) -> TEST b
          (bound at TESTMonad.hs:16:5)
Failed, modules loaded: none.

我清楚地知道我可能以錯誤的方式做很多事情,但我不知道它們是什么。 任何評論將不勝感激。 先感謝您!

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 ,所以它也不知道fx可能是什么類型。 結果,除了按原樣使用它之外,您實際上無法對它做任何事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM