作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将以下类(class)放在一起Domain
及其实例TrivialDomain
{-# LANGUAGE TypeFamilies #-}
data Transition = Transition
class Domain d where
type Set d
type Engine d :: * -> *
top :: Engine d (Set d)
-- ...
complement :: Set d -> Engine d (Set d)
exclude :: Set d -> Set d -> Engine d (Set d)
-- ...
data TrivialDomain = TrivialDomain
instance Domain TrivialDomain where
type Set TrivialDomain = [Int]
type Engine TrivialDomain = IO
top = return [0..10]
-- ...
complement a = top >>= (flip exclude) a
exclude a b = return $ filter (not . (`elem` b)) a
-- ...
test3.hs:25:21:
Couldn't match type ‘Engine d0’ with ‘IO’
The type variable ‘d0’ is ambiguous
Expected type: IO (Set d0)
Actual type: Engine d0 (Set d0)
In the first argument of ‘(>>=)’, namely ‘top’
In the expression: top >>= (flip exclude) a
test3.hs:25:35:
Couldn't match type ‘Set d1’ with ‘[Int]’
The type variable ‘d1’ is ambiguous
Expected type: Set d0 -> [Int] -> IO [Int]
Actual type: Set d1 -> Set d1 -> Engine d1 (Set d1)
In the first argument of ‘flip’, namely ‘exclude’
In the second argument of ‘(>>=)’, namely ‘(flip exclude) a’
Engine d (Set d)
解析为
IO [Int]
在实例声明中,似乎并非如此。至少 GHC 不这么认为。我错过了什么?
最佳答案
在您的情况下,关联类型不足以推断方法的类型。
你有课Domain d
, 和 Set
和 Engine
关联到 d
.这意味着只要有一个已知的 d
在我们的程序中,已知 Domain d
例如,GHC 可以解析 Set d
和 Engine d
.但这并不适用。 GHC 无法解析 d
或 Domain
来自 Set d
的实例或 Engine d
, 因为完全有可能有不同的 Domain
具有相同 Set
的实例和 Engine
类型。
因为你的类方法只提到 Set
和 Engine
, Domain d
永远不能从方法使用中推断出来。
你可以根据你的目标做几件事。
首先,您可以制作 d
取决于 Set
和 Engine
:
class Domain set engine where
type DomainOf set engine :: *
-- ...
FunctionalDependencies
为您提供更大的灵 active 来强制类型之间的依赖关系。比如可以明确声明只有一个
d
对于每个
Set
,这足以恢复良好的类型推断:
class Domain d set engine | d -> set engine, set -> d where
top :: engine set
complement :: set -> engine set
exclude :: set -> set -> engine set
data TrivialDomain = TrivialDomain
instance Domain TrivialDomain [Int] IO where
top = return [0..10]
complement a = top >>= (flip exclude) a
exclude a b = return $ filter (not . (`elem` b)) a
Proxy d
方法的参数,以使实例和关联的类型可解析:
import Data.Proxy
data Transition = Transition
class Domain d where
type Set d
type Engine d :: * -> *
top :: Proxy d -> Engine d (Set d)
complement :: Proxy d -> Set d -> Engine d (Set d)
exclude :: Proxy d -> Set d -> Set d -> Engine d (Set d)
data TrivialDomain = TrivialDomain
instance Domain TrivialDomain where
type Set TrivialDomain = [Int]
type Engine TrivialDomain = IO
top _ = return [0..10]
complement d a = top d >>= (flip (exclude d)) a
exclude d a b = return $ filter (not . (`elem` b)) a
Proxy d
的目的|是准确指定您要使用的实例。
top (Proxy :: Proxy d)
在每种方法的使用上(与其他方法类似),这是相当繁重的。对于 GHC 8,我们可以省略
Proxy
s 并使用
TypeApplications
反而:
{-# language TypeApplications, TypeFamilies #-}
-- ...
instance Domain TrivialDomain where
type Set TrivialDomain = [Int]
type Engine TrivialDomain = IO
top = return [0..10]
complement a = top @TrivialDomain >>= (flip (exclude @TrivialDomain)) a
exclude a b = return $ filter (not . (`elem` b)) a
关于haskell - Haskell 类型族中的类型歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36175839/
在C中,protocol family被提及为第一个参数。 例如: ipv4 的套接字(AF_INET,,) socket(AF_PACKET,,) 用于数据包嗅探 Python 支持三个地址族:AF
根据 vfork() 手册页,如果 vfork() 在调用 _exit 或 exec 之前修改除 pid_t 之外的任何数据,则行为未定义系统调用系列。 由此我了解到,如果vfork()创建的子进程调
我是一名优秀的程序员,十分优秀!