【发布时间】:2014-07-28 06:08:50
【问题描述】:
我正在使用 GADT 为货币创建一个基本维度(如物理维度)系统。维度(例如 USD、USD/EUR、EUR/USD)表示为虚拟类型。 我希望能够以例如样式打印一定数量的货币“10.3USD”或“0EUR”以及例如“10.3USD/EUR”使用显示。 我不太清楚如何解释我的问题,所以我将举一个例子来说明我是如何解决它的:
{-# LANGUAGE GADTs #-}
class (Show a) => Currency a where unphantom :: a
data USD = USD deriving Show
data EUR = EUR deriving Show
instance Currency USD where unphantom = USD
instance Currency EUR where unphantom = EUR
data Amount a where
Amount :: Currency a => Float -> Amount a
instance Show (Amount a) where
show (Amount x) = show x ++ show (unphantom :: a)
data Rate a b where
Rate :: (Currency a, Currency b) => Float -> Rate a b
-- ...
使用此代码,我得到了错误
$ ghc example.hs
[1 of 1] Compiling Main ( example.hs, example.o )
example.hs:14:37:
Could not deduce (Currency a1) arising from a use of `unphantom'
from the context (Currency a)
bound by a pattern with constructor
Amount :: forall a. Currency a => Float -> Amount a,
in an equation for `show'
at example.hs:14:9-16
Possible fix:
add (Currency a1) to the context of
an expression type signature: a1
or the data constructor `Amount'
or the instance declaration
In the first argument of `show', namely `(unphantom :: a)'
In the second argument of `(++)', namely `show (unphantom :: a)'
In the expression: show x ++ show (unphantom :: a)
我必须说,当我指定 a 时,我必须说我不明白为什么在这种情况下编译器正在谈论 a1 类型。
当然,我想避免在 haskell 类型系统之外表示维度,因为这为我添加了额外的样板代码,并且据我所知理论上是不必要的(即编译器应该有足够的信息来推断如何显示编译时的数量或速率)(并在运行时增加一点开销)。
【问题讨论】:
-
作为与您的问题或我的回答无关的注释......我强烈建议将此问题发送给代码审查,因为有很多可以改进的地方。
-
好吧,我创建了这篇文章:codereview.stackexchange.com/questions/58261/…
标签: haskell gadt phantom-types