开发者

Haskell beginner question (defining pairs, similar to Http statuses)

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开发者_Go百科
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")]


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜