我该如何重构这段代码

时间:2014-07-24 04:56:12

标签: haskell

我正在尝试重构以下(工作)代码(优秀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中,这样的重构是否可能(甚至是可取的)?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

您在这里使用f,它引用了<<=的第一个操作数。

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

在此处使用时,它指的是传递给go的函数。

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

选择一个不同的名字!