Haskell初学者问题(定义对,类似于Http状态)

时间:2011-09-26 21:40:15

标签: haskell tuples

我是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")]

3 个答案:

答案 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,根据需要优化性能。