功能依赖性和奇怪的刚性类型变量错误

时间:2019-03-25 00:59:44

标签: haskell

我试图弄清楚为什么此代码示例中无法识别返回类型,请参见runnable code here

{-# LANGUAGE TypeFamilies #-}

module Test where

import Control.Monad.IO.Class
import Control.Monad
import Control.Monad.Except
import Control.Exception
import Data.Typeable
import Control.Monad.State.Lazy

class Foo m where
  type Inner m :: * -> *
  bar :: Int -> m Int

instance (MonadIO w, Show s, Num s) => Foo (StateT s w) where
  bar current = do
    a <- get
    return a -- error
    -- return 24 -- ok

program :: StateT Int IO String
program = do
      r <- bar 42
      liftIO $ putStrLn $ "output= " ++ (show r)
      return $ "ok"

run :: IO ()
run = do
  (a, s) <- runStateT program $ 777
  putStrLn $ (show a) ++ (show s)

错误消息如下所示,在我的情况下,MonadState s1 (StateT s1 m)两个s1都应为Int,因此我不确定为什么不允许这样做。

• Couldn't match type ‘s’ with ‘Int’
    arising from a functional dependency between:
      constraint ‘MonadState Int (StateT s w)’
        arising from a use of ‘get’
      instance ‘MonadState s1 (StateT s1 m)’ at <no location info>
  ‘s’ is a rigid type variable bound by
    the instance declaration
    at fsm-try-5-3-q.hs:16:10-55
• In a stmt of a 'do' block: a <- get
  In the expression:
    do a <- get
       return a
  In an equation for ‘bar’:
      bar current
        = do a <- get
             return a

1 个答案:

答案 0 :(得分:1)

在定义Foo (StateT s w)实例时,您并没有将s约束为Int,但想从bar返回它。以后如何使用该实例无关紧要,因为该实例必须自己有效。

也许您想定义:

instance (MonadIO w) => Foo (StateT Int w) where
    type Inner (StateT Int w) = w
    bar current = do
        a <- get
        return a

Here is your REPL with the modified definition