Проблема с 'переменной жесткого типа' в монаде в haskell - PullRequest
1 голос
/ 14 июля 2020

Я пытаюсь лучше изучить монады и играю с этим в Haskell. Я определил монаду таким образом:

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.

Я точно знаю, что могу делать много вещей неправильным образом, но я понятия не имею, что это такое. Любой комментарий будет оценен. Заранее спасибо!

1 Ответ

1 голос
/ 14 июля 2020

Экземпляр 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 тоже может быть. В результате вы действительно ничего не можете с ним сделать, кроме как использовать его как есть.

...