Help me do this idiomatically (1/3)

data Context = Context Int

tagItems :: ([a], Context) -> ([(a, Int)], Context)
tagItems (ys, ctx) = foldl f ([], ctx) ys
  where f (items, (Context x)) y = (items ++ [(y, x)], Context (x + 1))

main :: IO ()
main = do
  let ctx = Context 1000
      (items, ctx') = tagItems (["one", "two", "three"], ctx)
  putStrLn $ show items
-- Yields: [("one",1000),("two",1001),("three",1002)]

Help me do this idiomatically (2/3)

import Data.List
import Data.Tuple

data Context = Context Int

tagItems :: ([a], Context) -> ([(a, Int)], Context)
tagItems (ys, ctx) = swap $ mapAccumL f ctx ys
  where f (Context x) y = (Context (x + 1), (y, x))

main :: IO ()
main = do
  let ctx = Context 1000
      (items, ctx') = tagItems (["one", "two", "three"], ctx)
  putStrLn $ show items
-- Yields: [("one",1000),("two",1001),("three",1002)]

Help me do this idiomatically (3/3)

  • Should I use foldl' or foldr instead?
  • If so, is it straightforward to maintain the ordering?
  • Is there a more idiomatic way to do this kind of thing?
  • How do I refactor this to use the state monad?
  • Should I refactor this to use the state monad?

x : xs efficiency problem mentioned in Real World Haskell

asPattern :: [a] -> [a]
asPattern xs@(x : xs') = xs

noAsPattern :: [a] -> [a]
noAsPattern (x : xs) = (x : xs)

  • Claim is that asPattern is more efficient than noAsPattern
  • There are many comments about this in annotated online version of book
  • Given how sophisticated GHC is reputed to be, it would worry me if the fairly obvious optimization isn't automatic
  • What's the consensus?

Search and replace with ByteString

  • Documentation is here
  • Documentation for Data.ByteString.Search.replace claims:
    replace :: Substitution rep => ByteString -> rep -> ByteString -> ByteString
  • But, GHCI says:
    replace :: Substitution rep => B.ByteString -> rep -> B.ByteString -> LB.ByteString
  • To be fair, the documentation mentions the laziness of the result in passing
  • But, that's kind of confusing
  • How do I search and replace multiple strings?

Language extension of interest: view patterns

{-# LANGUAGE ViewPatterns #-}

-- Abstract type: data constructor would typically not be exported
data Widget = Widget String String
createWidget n d = Widget n d
widgetName (Widget n _) = n
widgetDesc (Widget _ d) = d

-- View type and function dependent only on public interface
data WidgetV = WidgetV String String
widgetV w = WidgetV n d where n = widgetName w; d = widgetDesc w

-- Function that pattern-matches on view
demo (widgetV -> WidgetV n d) = "name = " ++ n ++ " desc = " ++ d

main = putStrLn $ demo $ createWidget "name" "desc"