Miranda To Haskell - 改进版本是什么?

时间:2015-08-20 22:59:26

标签: haskell

我正在编写this论文中的代码。我的翻译更加冗长,这让我感到烦恼。它发生在我身上,我错过了一些显而易见的东西,使其像原来的米兰达一样简洁。

这是米兰达:

fix :: qtree(*) -> qtree(*)
fix(Leaf(x)) = Leaf(x)
fix(Internal(nw, ne, sw, se)) =
   merge(Internal(fix(nw), fix(ne), fix(sw), fix(se)))
   where
      merge(Internal (Leaf(x), Leaf(x), Leaf(x), Leaf(x))) = Leaf(x)
      merge(other) = other

注意merge的LHS。它捕获了所有四个叶子具有相同值的情况。无法对Haskell进行直接音译,因为我会对x的多个定义抱怨。这是我的版本:

fix :: (Eq a) => QTree a -> QTree a
fix (Leaf a) = Leaf a
fix (Internal nw ne sw se) =
   merge (Internal (fix nw) (fix ne) (fix sw) (fix se))
      where
   merge internal@(Internal (Leaf w) (Leaf x) (Leaf y) (Leaf z))
     | (w == x) && (x == y) && (y == z) = Leaf x
     | otherwise                        = internal
   merge other = other

如何更接近Miranda代码中发生的事情?

2 个答案:

答案 0 :(得分:13)

作为参考,具有重复名称的模式称为非线性。 Miranda支持这些,而Haskell则不支持。这是原始 Haskell设计委员会在1988中所做的设计权衡。 This thread有一些额外的理由不支持Haskell中的非线性模式。

不幸的是,这意味着你无法使用Haskell的模式匹配来接近Miranda。您必须编写一些明确比较相等值的代码,就像您一样。

你也可以让你的平等检查更短,但你无法完全摆脱检查。这是一个对我来说似乎有点改进的版本:

othewise

答案 1 :(得分:7)

你可能会发现uniplate或类似的东西对你的四叉树非常有用:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics.Uniplate.Data
import Data.Data(Data)
import Data.Typeable(Typeable)

data QTree a = Internal (QTree a) (QTree a) (QTree a) (QTree a)
             | Leaf a
             deriving (Data,Typeable -- for uniplate
                       , Eq, Show)
-- not tested:
fix :: (Data a, Eq a) => QTree a -> QTree a
fix t = case map fix $ children t of
  lw@(Leaf w):xyz
    | all (lw ==) xyz -> lw
  _                   -> t

这些简单的泛型加上我们在case中将谓词与模式匹配相结合的能力,修复了实际上对两个版本都是重复的相同分支的困扰。