haskell-ja > Archives > 2012/02/24

2012/02/24 04:51:56 UTCshelarcy@twitter
#
ByteString や Text なら uncons 関数を使うという手もありますね。 http://t.co/tbLwfbsS http://t.co/uy0gVINv
2012/02/24 04:52:22 UTCshelarcy
#
import qualified Data.ByteString as BS

foo bs =
 case BS.uncons bs of
   Nothing -> undefined
   Just (x,xs) ->
     case BS.null xs of
       True -> undefined
       _    -> undefined
#
import qualified Data.Text as T

foo txt =
 case T.uncons txt of
   Nothing -> undefined
   Just (x,xs) ->
     case T.null xs of
       True -> undefined
       _    -> undefined
#
> foo を ByteString や Text で書き直す
2012/02/24 04:58:58 UTCshelarcy@twitter
#
綺麗にみえるように uncons 関数を使って最初に処理を分岐する形にしていますけれど、実際には null 関数を使って最初に分岐するようにした方が良いですね。
2012/02/24 05:15:09 UTCshelarcy@twitter
#
view パターンを使うと、こんな感じでしょうか。
2012/02/24 05:15:16 UTCshelarcy
#
{-# LANGUAGE ViewPatterns #-}
import qualified Data.Text as T

foo (T.null -> True)           = undefined
-- Just to avoid warning about non-exhaustive pattern ...
foo (T.uncons -> Nothing)        = undefined
foo (T.uncons -> Just (x, xs)) =
  case T.null xs of
    True -> undefined
    _    -> undefined
#
{-# LANGUAGE ViewPatterns #-}
import Data.Maybe (fromJust)
import qualified Data.Text as T

foo (T.null -> True)           = 1
foo (T.uncons -> T.null . snd . fromJust -> True) = undefined
foo txt = undefined
#
あっ、 s/1/undefined/ です。
2012/02/24 05:27:34 UTCkazu
#
ありがとうございます。最初に null で分岐する心はなんでしょうか? あと、view の最初のコードだと、uncons は 2 回評価されてしまうのでしょうか?
2012/02/24 05:42:11 UTCshelarcy@twitter
#
あっ、uncons を使って空かどうか確かめても、null を使って空かどうか確かめても同じですね。杞憂でした。 http://t.co/smiffbPA http://t.co/PPXMN5ak
2012/02/24 05:43:15 UTCshelarcy
#
uncons で空かどうか確かめるよりも、null で空かどうか確かめた方がコストが低くなると考えたためです。ただ、さっき書いたように杞憂でした……。 > 最初に null で分岐する心
2012/02/24 05:53:12 UTCshelarcy@twitter
#
-ddump-ds してみれば分かると思いますが、uncons が評価されるのは最初の一度だけですね。
2012/02/24 05:54:10 UTCshelarcy
#
Result size = 33

Test.foo :: forall a_ajs. Data.Text.Internal.Text -> a_ajs
[LclIdX]
Test.foo =
  \ (@ a_aju) (ds_djE :: Data.Text.Internal.Text) ->
    case Data.Text.null ds_djE of _ {
      __DEFAULT ->
        (\ _ ->
           case Data.Text.uncons ds_djE of _ {
             Data.Maybe.Nothing -> GHC.Err.undefined @ a_aju;
             Data.Maybe.Just ds_djH ->
               case ds_djH of _ { (_, xs_afu) ->
               case Data.Text.null xs_afu of _ {
                 __DEFAULT ->
                   (\ _ -> GHC.Err.undefined @ a_aju) GHC.Prim.realWorld#;
                 GHC.Types.True -> GHC.Err.undefined @ a_aju
               }
               }
           })
          GHC.Prim.realWorld#;
      GHC.Types.True -> GHC.Err.undefined @ a_aju
    }
2012/02/24 06:06:13 UTCshelarcy@twitter
#
なお、desugar のされ方こそ違うものの、最適化結果は全て同じコードになるようです。(GHC 7.4.1)