2014-07-24 134 views
1

我試圖重構以下(工作)代碼(優秀NICTA Haskell course的一部分):我如何重構這個代碼

instance Extend ListZipper where 
    f <<= z = 
    ListZipper (unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . moveLeft) z) 
       (f z) 
       (unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . moveRight) z) 

以下幾點:

instance Extend ListZipper where 
    f <<= z = ListZipper (go moveLeft) (f z) (go moveRight) 
     where go f = unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . f) z 

但不幸的是,我得到以下編譯錯誤:

src/Course/ListZipper.hs:669:25: 
    Couldn't match type `b' with `MaybeListZipper a' 
     `b' is a rigid type variable bound by 
      the type signature for 
      <<= :: (ListZipper a -> b) -> ListZipper a -> ListZipper b 
      at src/Course/ListZipper.hs:669:3 
    Expected type: List b 
     Actual type: List (MaybeListZipper a) 
    In the return type of a call of `go' 
    In the first argument of `ListZipper', namely `(go moveLeft)' 
    In the expression: ListZipper (go moveLeft) (f z) (go moveRight) 


我錯過了一些小東西或者更重要的東西嗎?

在慣用的Haskell中,這樣的重構是否可能(甚至是理想的)?

回答

4

您正在使用新的f遮蓋原始f。嘗試重命名第二個f,如

instance Extend ListZipper where 
    f <<= z = ListZipper (go moveLeft) (f z) (go moveRight) 
     where go g = unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . g) z 
3

您在這裏使用f,它指的是<<=的第一個操作數。

(unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . moveLeft) z) 

當你在這裏使用它時,它指的是傳遞給go的函數。

where go f = unfoldr ((<$>) (\z' -> (f z', z')) . toOptional . f) z 

選擇一個不同的名字!

+0

不幸的是,我只能「接受」一個答案。 – tonyday