Haskell 幻影类型混淆?
我对幻影类型的使用感到困惑:Haskell 幻影类型混淆?,haskell,phantom-types,Haskell,Phantom Types,我对幻影类型的使用感到困惑: type Words = String type Numbers = Int data NonPhantom = NP1 Words | NP2 Numbers deriving (Show) data Phantom a = P1 Words | P2 Numbers deriving (Show) nonPhantomFunction :: NonPhantom -> Int nonPhantomFunction r = 100 phantom
type Words = String
type Numbers = Int
data NonPhantom = NP1 Words | NP2 Numbers deriving (Show)
data Phantom a = P1 Words | P2 Numbers deriving (Show)
nonPhantomFunction :: NonPhantom -> Int
nonPhantomFunction r = 100
phantomFunction :: Phantom Numbers -> Int
phantomFunction a = 2001
main = do
print $ nonPhantomFunction (NP1 "sdsdds") --can also pass NP2 here!
print $ phantomFunction (P1 "sdsdsd") --This shouldn't work!?
我希望此代码不会编译,因为phantomFunction
明确声明了其数字的幻影的预期数据类型Phantom
但是这编译得好吗?我做错了什么
data Phantom a = P1 Words | P2 Numbers deriving (Show)
这使得任何类型的P1“aa”
形式的Phantom a
,对于任何a
,包括数字
,构造函数的参数和构造函数所属类型的类型参数之间没有隐式连接。如果希望类型参数表示的类型出现在构造函数的参数中的任何位置,则需要显式声明它
您也可以在以下表达式中看到这一点:
Nothing
[]
第一个可以为任何a
创建可能是一个,第二个可以为任何a
创建一个列表[a]
同样地
P1 "xyz"
根据您的示例,可以为任何a
生成幻影a
,其他答案已经解释了构造函数的类型
P1 :: Words -> Phantom a
意味着它能够为a
的任何选择构造类型为p1a
的值;特别是对于a~数字的选择
。这就是函数调用的原因
phantomFunction (P1 "sdsdsd")
打字检查
现在,你如何解决这个问题?我想你想要P1::Words->Phantom Words
?GADT允许您通过写入来约束构造值的类型中出现的类型变量
{-# LANGUAGE GADTs #-}
data Phantom a where
P1 :: Words -> Phantom Words
P2 :: Numbers -> Phantom Numbers
这将
- 确保
P1
具有类型Phantom Words
,因此不能使用它构建Phantom number
- 允许使用
虚字的函数通过仅在P1
- 允许在Phantom a上多态的函数基于模式匹配(这是一个大的)来优化它们的类型,因此您可以编写
dup :: Phantom a -> a
dup (P1 ws) = ws ++ ws -- Here, we have to return a Words, and ws is a Words, so ++ will work
dup (P2 n) = n + n -- Here, we have to return a Numbers, and x is a Numbers, so + will work
也许你想要一个GADT?