- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
唐·斯图尔特的Haskell in the Large的演示中提到了幻影类型:
data Ratio n = Ratio Double
1.234 :: Ratio D3
data Ask ccy = Ask Double
Ask 1.5123 :: Ask GBP
我读了他的要点,但我不明白。另外,我读了Haskell Wiki关于这个话题。但我仍然没有明白他们的观点。
使用幻像类型的动机是什么?
最佳答案
回答“使用幻像类型的动机是什么”。有两点:
例如,您可以使用长度单位标记距离:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Distance a = Distance Double
deriving (Num, Show)
data Kilometer
data Mile
marathonDistance :: Distance Kilometer
marathonDistance = Distance 42.195
distanceKmToMiles :: Distance Kilometer -> Distance Mile
distanceKmToMiles (Distance km) = Distance (0.621371 * km)
marathonDistanceInMiles :: Distance Mile
marathonDistanceInMiles = distanceKmToMiles marathonDistance
你可以避免Mars Climate Orbiter disaster :
>>> marathonDistanceInMiles
Distance 26.218749345
>>> marathonDistanceInMiles + marathonDistance
<interactive>:10:27:
Couldn't match type ‘Kilometer’ with ‘Mile’
Expected type: Distance Mile
Actual type: Distance Kilometer
In the second argument of ‘(+)’, namely ‘marathonDistance’
In the expression: marathonDistanceInMiles + marathonDistance
<小时/>
这个“模式”有轻微的变化。您可以使用DataKinds
来拥有封闭的单位集:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
data LengthUnit = Kilometer | Mile
newtype Distance (a :: LengthUnit) = Distance Double
deriving (Num, Show)
marathonDistance :: Distance 'Kilometer
marathonDistance = Distance 42.195
distanceKmToMiles :: Distance 'Kilometer -> Distance 'Mile
distanceKmToMiles (Distance km) = Distance (0.621371 * km)
marathonDistanceInMiles :: Distance 'Mile
marathonDistanceInMiles = distanceKmToMiles marathonDistance
它的工作原理类似:
>>> marathonDistanceInMiles
Distance 26.218749345
>>> marathonDistance + marathonDistance
Distance 84.39
>>> marathonDistanceInMiles + marathonDistance
<interactive>:28:27:
Couldn't match type ‘'Kilometer’ with ‘'Mile’
Expected type: Distance 'Mile
Actual type: Distance 'Kilometer
In the second argument of ‘(+)’, namely ‘marathonDistance’
In the expression: marathonDistanceInMiles + marathonDistance
但是现在距离
只能以公里或英里为单位,以后我们无法添加更多单位。这在某些用例中可能很有用。
我们还可以这样做:
data Distance = Distance { distanceUnit :: LengthUnit, distanceValue :: Double }
deriving (Show)
在距离情况下,我们可以计算出加法,例如,如果涉及不同的单位,则转换为公里。但这对于货币来说效果不佳,因为货币的比率随着时间的推移并不是恒定的等。
<小时/>并且可以使用 GADT 来代替,这在某些情况下可能是更简单的方法:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
data Kilometer
data Mile
data Distance a where
KilometerDistance :: Double -> Distance Kilometer
MileDistance :: Double -> Distance Mile
deriving instance Show (Distance a)
marathonDistance :: Distance Kilometer
marathonDistance = KilometerDistance 42.195
distanceKmToMiles :: Distance Kilometer -> Distance Mile
distanceKmToMiles (KilometerDistance km) = MileDistance (0.621371 * km)
marathonDistanceInMiles :: Distance Mile
marathonDistanceInMiles = distanceKmToMiles marathonDistance
现在我们知道了值(value)层面上的单位:
>>> marathonDistanceInMiles
MileDistance 26.218749345
<小时/>
这种方法极大地简化了 Aadit's answer 中的 Expr
示例。 :
{-# LANGUAGE GADTs #-}
data Expr a where
Number :: Int -> Expr Int
Boolean :: Bool -> Expr Bool
Increment :: Expr Int -> Expr Int
Not :: Expr Bool -> Expr Bool
<小时/>
值得指出的是,后面的变体需要不平凡的语言扩展(GADTs
、DataKinds
、KindSignatures
),这可能不是您的编译器支持。 Don 提到的 Mu 编译器 可能就是这种情况。
关于haskell - 幻象类型背后的动机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28247543/
为了了解 Redux 的动机,我阅读了官方链接 https://redux.js.org/introduction/motivation还有这个 stackoverflow 问题 Explain Re
您好,这个 firebase 函数曾经可以工作,但知道它现在工作时间更长了,我收到此错误消息 Function returned undefined, expected Promise or valu
我是一名优秀的程序员,十分优秀!