给出定义:
{-# LANGUAGE ExistentialQuantification, TypeFamilies, FlexibleInstances, FlexibleContexts, ScopedTypeVariables #-}
class Monad m => RunableMonad m where
type ReturnType m :: * -> *
run :: m a -> ReturnType m a
当我输入 GHCI 时
:t \x -> [run $ return x]
它给了我正确的表达式类型:
\x -> [run $ return x] :: RunableMonad m => a -> [ReturnType m a]
但是当我将以下定义放入文件中时,它给出了类型错误:
single :: RunableMonad m => a -> [ReturnType m a]
single x = [run $ return x]
Could not deduce (ReturnType m0 ~ ReturnType m)
from the context (RunableMonad m)
bound by the type signature for
single :: RunableMonad m => a -> [ReturnType m a]
at concurrency-simulator.hs:467:11-49
NB: ‘ReturnType’ is a type function, and may not be injective
The type variable ‘m0’ is ambiguous
Expected type: a -> [ReturnType m a]
Actual type: a -> [ReturnType m0 a]
In the ambiguity check for:
forall a (m :: * -> *). RunableMonad m => a -> [ReturnType m a]
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature for ‘single’:
single :: RunableMonad m => a -> [ReturnType m a]
最佳答案
我认为在这种情况下 GHCi 的 :t
的结果本质上是错误的,并且您将永远无法实际使用表达式 run $ return x
.
问题是你的类定义中没有限制说两个不同的 Monad
s m0
和 m
(使用与错误消息的名称相同)不能具有相同 ReturnType
。
这意味着,当查看使用 run $ return x
的上下文时,GHC 可能能够推断出结果 ReturnType m a
是什么,并从x
的类型可以推断出 a
是什么,但无法从中推断出实际的 monad m
是什么。
但是,您应该能够明确地告诉它:run (return x::WhateverTypeYouReallyWant)
。
仅当您在像 return x
这样的表达式上使用 run
时才需要添加显式类型注释,该表达式具有多态性,可以属于多个 monad。 (或者任何单子(monad),在这种情况下。)
关于haskell - 在 GHCI 中时正确的行为,在文件中时键入错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24376338/