
Hi Daniel, I really like your translation of ulast' below ulast' y ys = case ys of [] -> y z:zs -> ulast' z zs This makes it really clear there is only one comparison happening. I tried looking at core with the -O option (ghc 7.6.3), but am having a had time making sense of it. For comparison, could you also translate the inefficient version of plast into the case notation you use above? Thanks, Dimitri ==================== Tidy Core ==================== Result size of Tidy Core = {terms: 49, types: 58, coercions: 0} lvl_rgS :: [GHC.Types.Char] [GblId] lvl_rgS = GHC.CString.unpackCString# "empty list!" Test.ulast2 :: forall a_b. a_b [GblId, Str=DmdType b] Test.ulast2 = \ (@ a_b) -> GHC.Err.error @ a_b lvl_rgS Rec { Test.ulast1 [Occ=LoopBreaker] :: forall a_b. a_b -> [a_b] -> a_b [GblId, Arity=2, Caf=NoCafRefs, Str=DmdType LS] Test.ulast1 = \ (@ a_b) (y_aeQ :: a_b) (ds_df8 :: [a_b]) -> case ds_df8 of _ { [] -> y_aeQ; : y1_aeR ys_aeS -> Test.ulast1 @ a_b y1_aeR ys_aeS } end Rec } Test.ulast :: forall a_aeH. [a_aeH] -> a_aeH [GblId, Arity=1, Str=DmdType S, Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=1, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 50 0}] Test.ulast = \ (@ a_b) (ds_df6 :: [a_b]) -> case ds_df6 of _ { [] -> Test.ulast2 @ a_b; : x_aeN xs_aeO -> Test.ulast1 @ a_b x_aeN xs_aeO } lvl1_rgT :: forall a_d. a_d [GblId, Str=DmdType b] lvl1_rgT = \ (@ a_d) -> GHC.Err.error @ a_d lvl_rgS Rec { Test.plast [Occ=LoopBreaker] :: forall a_aeI. [a_aeI] -> a_aeI [GblId, Arity=1, Str=DmdType S] Test.plast = \ (@ a_d) (ds_dfc :: [a_d]) -> case ds_dfc of _ { [] -> lvl1_rgT @ a_d; : x_aeJ ds1_dfd -> case ds1_dfd of wild1_X8 { [] -> x_aeJ; : ipv_sfz ipv1_sfA -> Test.plast @ a_d wild1_X8 } } end Rec } ======