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

发布于 2024-12-06 15:15:25 字数 833 浏览 0 评论 0原文

我是 Haskell 初学者,必须定义一系列由 Int 和 String / ByteString 组成的已知状态,类似于 HTTP 状态,

我永远不需要从状态消息中获取状态代码。但是,我必须获取给定状态代码的状态消息。

我查看了 Network.HTTP.Types,它们为每个可能的状态代码定义了不同的“变量”、“status200”、“status201”等(类似于下面的“FoodTwo.hs”)。

如果我刚刚定义了一个返回状态代码的状态消息的函数(如下面的“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")]

I'm a Haskell beginner and have to define a series of known statuses that consist of an Int and a String / ByteString, similar to HTTP Statuses

I will never have to get a status code from a status message. However I will have to get a status message for a given status code.

I've had a look at Network.HTTP.Types and they define distinct 'variables', "status200", "status201", etc. for every possible status code (similar to "FoodTwo.hs" below).

What are the (performance?) implications if I just defined a function that returns status messages for status codes, as shown in "FoodOne.hs" below?

On top of that, in languages like C# or Java one would probably declare a static dictionary, similar to FoodThree.hs - I somehow doubt this is the Haskell way? Why?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怂人 2024-12-13 15:15:25
-- 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 方式。选择一种能够在开发人员烦恼、速度和内存消耗之间进行适当权衡的语言,就像使用任何其他语言一样。

-- FoodOne.hs
statusMessage :: Int -> String
statusMessage 30 = "BBQ ready"
statusMessage 40 = "Beverages served"
statusMessage rest = "Unknown Food Status"

Most compilers are will compile this to a linear search, so it will have linear runtime cost.

-- FoodTwo.hs
data FoodStatus = FoodStatus {
    fstatusCode :: Int,
    fstatusMessage :: String
}

status30 = FoodStatus 30 "BBQ ready"
status40 = FoodStatus 40 "Beverages served"

This approach is not comparable to the others: it doesn't provide status lookup given a (dynamically-known) Int. However, for statically-known Ints, it is the fastest: the lookup is done once at compile-time and therefore has constant runtime cost, regardless of how many different constants there are.

-- FoodThree.hs
statusMessages = [(30,"BBQ ready"),(40,"Beverages served")]

Doing naive lookup in this list (e.g. by the built-in lookup function) will involve linear search, and therefore have linear runtime cost.

-- 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)

The Data.Map module implements balanced search trees, and each lookup takes logarithmic time in the number of different statuses. You might also consider Data.IntMap, which also takes logarithmic time, but has better constants.

-- 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'

The Data.Array module implements immutable arrays, and each lookup takes constant time. If your array is sparse, however, this may have higher memory costs than the alternatives.

These are all the Haskell way. Choose the one with the right tradeoffs between developer annoyance, speed, and memory consumption for you, just as you would in any other language.

人海汹涌 2024-12-13 15:15:25
-- 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
-- FoodThree.hs
statusMessages = [(30,"BBQ ready"),(40,"Beverages served")]

This can easily be used in Haskell:

fromCode n = fromMaybe "No such error" $ find ((==) n . fst) statusMessages

Or you can use 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
甜扑 2024-12-13 15:15:25

像下面这样的东西可以吗?

data FoodStatus = BBQ_READY | BEVERAGES_SERVED | ...

instance Show FoodStatus where ...

toCode status = ...
fromCode num = ...

这与 FoodOne.hs 很相似,但更抽象,因此更易于操作。您可以按照自己的意愿自由地实现 fromCode,并根据需要优化性能。

Would something like the following serve?

data FoodStatus = BBQ_READY | BEVERAGES_SERVED | ...

instance Show FoodStatus where ...

toCode status = ...
fromCode num = ...

This is pretty much FoodOne.hs but more abstract and thus more manipulable. You are free to implement fromCode however you wish, optimizing for performance as needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文