我是Haskell的初学者,必须定义一系列由Int和String / ByteString组成的已知状态,类似于HTTP状态
我永远不必从状态消息中获取状态代码。但是,我必须获取给定状态代码的状态消息。
我已经看过Network.HTTP.Types,他们为每个可能的状态代码定义了不同的'变量',“status200”,“status201”等(类似于下面的“FoodTwo.hs”)。 / p>
如果我刚刚定义了一个返回状态代码状态消息的函数,那么(性能?)含义是什么,如下面的“FoodOne.hs”所示?
最重要的是,在像C#或Java这样的语言中,可能会声明一个静态字典,类似于FoodThree.hs - 我不知道这是否是Haskell方式?为什么呢?
-- FoodOne.hs
statusMessage :: Int -> String
statusMessage 30 = "BBQ ready"
statusMessage 40 = "Beverages served"
statusMessage rest = "Unknown Food Status"
-- FoodTwo.hs
data FoodStatus = FoodStatus {
fstatusCode :: Int,
fstatusMessage :: String
}
status30 = FoodStatus 30 "BBQ ready"
status40 = FoodStatus 40 "Beverages served"
-- FoodThree.hs
statusMessages = [(30,"BBQ ready"),(40,"Beverages served")]
答案 0 :(得分:5)
-- FoodOne.hs
statusMessage :: Int -> String
statusMessage 30 = "BBQ ready"
statusMessage 40 = "Beverages served"
statusMessage rest = "Unknown Food Status"
大多数编译器都会将其编译为线性搜索,因此它将具有线性运行时成本。
-- FoodTwo.hs
data FoodStatus = FoodStatus {
fstatusCode :: Int,
fstatusMessage :: String
}
status30 = FoodStatus 30 "BBQ ready"
status40 = FoodStatus 40 "Beverages served"
这种方法与其他方法不具有可比性:它不提供给定(动态已知)Int
的状态查找。但是,对于静态已知的Int
,它是最快的:查找在编译时完成一次,因此具有恒定的运行时成本,无论有多少不同的常量。
-- FoodThree.hs
statusMessages = [(30,"BBQ ready"),(40,"Beverages served")]
在此列表中执行天真查找(例如,通过内置的lookup
函数)将涉及线性搜索,因此具有线性运行时成本。
-- FoodFour.hs
import Data.Map as M
statusMessages = fromList [(30, "BBQ ready"),(40,"Beverages served")]
message n = fromMaybe "Unknown Food Status" (M.lookup n statusMessages)
Data.Map
模块实现平衡搜索树,每个查找以不同状态数的对数时间。您也可以考虑Data.IntMap
,它也需要对数时间,但具有更好的常数。
-- FoodFive.hs
import Data.Array as A
(statusLo, statusHi) = (30, 40)
statusMessages = listArray (statusLo, statusHi)
[ Just "BBQ ready"
, Nothing
, Nothing
, {- ... -}
, Just "Beverages served"
]
message' n = guard (statusLo <= n && n <= statusHi) >> statusMessages ! n
message = fromMaybe "Unknown Food Status" . message'
Data.Array
模块实现不可变数组,每次查找都需要一些时间。但是,如果您的阵列很稀疏,那么这可能比替代方案具有更高的内存成本。
这些是所有 Haskell方式。选择 you 之间在开发者烦恼,速度和内存消耗之间进行权衡的权衡,就像在其他任何语言中一样。
答案 1 :(得分:3)
-- FoodThree.hs
statusMessages = [(30,"BBQ ready"),(40,"Beverages served")]
这很容易在Haskell中使用:
fromCode n = fromMaybe "No such error" $ find ((==) n . fst) statusMessages
或者您可以使用Data.Map:
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
codemap = Map.fromList statusMessages
fromCode n = fromMaybe "No such error" $ Map.lookup n codemap
答案 2 :(得分:1)
以下情况会发生吗?
data FoodStatus = BBQ_READY | BEVERAGES_SERVED | ...
instance Show FoodStatus where ...
toCode status = ...
fromCode num = ...
这几乎是FoodOne.hs,但更抽象,因此更易于操作。您可以自由地实现fromCode,根据需要优化性能。