我正在准备考试的作业之一让我创造了
data Exp = T | F | And Exp Exp | Or Exp Exp | Not Exp deriving (Eq, Show, Ord, Read)
然后它要求制作
折叠 :: a -
这就是我想到的
folde :: a -> a -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> Exp -> a
folde t f a o n T = t
folde t f a o n F = f
folde t f a o n (And x y) = a (folde t f a o n x) (folde t f a o n y)
folde t f a o n (Or x y) = o (folde t f a o n x) (folde t f a o n y)
folde t f a o n (Not x) = n (folde t f a o n x)
该作业要求
evb
、evi
和 evh
。
它们都应该使用正确的参数对folde进行一次调用。
Evb 计算布尔表达式。
evb :: Exp -> Bool
evb = folde True False (&&) (||) not
Evi计算为整数,将
T
视为Int 1
,将F
视为Int 5
,将And
视为,将
或
视为*
和Not
视为否定。
evi :: Exp -> Int
evi = folde 1 5 (+) (*) negate
到目前为止还不错,一切正常。我也很乐意收到有关此的任何反馈。
然而,我似乎不明白如何解决
evh
evh
应该计算树的高度。
它应该是
evh :: Exp -
赋值说它应该将
T
和F
视为高度1
。它继续说Not x
应该评估为高度x 1
。And
andand
的or
具有其最高子树1高度。
我似乎不知道应该将什么传递给我的
folde
函数
赋值说它应该将T
和F
视为高度1
。它继续说Not x
应该评估为高度x 1
。And
andand
or
具有其最高子树1
的高度。
您可以使用显式递归非常直接地编写:
height T = 1
height F = 1
height (Not x) = height x + 1
height (And x y) = max (height x) (height y) + 1
height (Or x y) = max (height x) (height y) + 1
现在,您如何使用
folde
编写它?递归折叠的关键在于folde
为您的每个函数提供折叠所有子树的结果。当您在And l r
上folde
时,它首先折叠两个子树,然后将这些结果传递给folde
的参数。因此,您无需手动调用高度x
,folde
将为您计算并将其作为参数传递,因此您自己的工作最终会像\x y-
heightT = 1 -- height T = 1
heightF = 1 -- height F = 1
heightN x = x + 1 -- height (Not x) = height x + 1
heightA l r = max l r + 1 -- height (And l r) = max (height l) (height r) + 1
heightO l r = max l r + 1 -- height (Or l r) = max (height l) (height r) + 1
喂
它们折叠,
并简化
height = folde 1 1 -- T F
ao -- And
ao -- Or
(+1) -- Not
where ao x y = max x y + 1
data ExpF a = T | F | Not a | And a a | Or a a
deriving (Functor, Foldable, Traversable)
这看起来像你的<code>Exp</code>,除了它没有递归之外,它有一个类型参数和一堆用于该类型值的孔。现在,看看
ExpF
下的表达式类型:
T :: forall a. ExpF a
Not F :: forall a. ExpF (ExpF a)
And F (Not T) :: forall a. ExpF (ExpF (ExpF a))
如果设置< code > a = ExpF(ExpF(ExpF(ExpF(ExpF(ExpF...))))
(on to infinity)在上述每一种情况下,您会发现它们都可以具有相同的类型:
T :: ExpF (ExpF (ExpF ...))
Not F :: ExpF (ExpF (ExpF ...))
And F (Not T) :: ExpF (ExpF (ExpF ...))
无限很有趣!我们可以使用
Fix
对这种无限递归类型进行编码
newtype Fix f = Fix { unFix :: f (Fix f) }
-- Compare
-- Type level: Fix f = f (Fix f)
-- Value level: fix f = f (fix f)
-- Fix ExpF = ExpF (ExpF (ExpF ...))
-- fix (1:) = 1:( 1:( 1: ...))
-- Recover original Exp
type Exp = Fix ExpF
-- Sprinkle Fix everywhere to make it work
Fix T :: Exp
Fix $ And (Fix T) (Fix $ Not $ Fix F) :: Exp
-- can also use pattern synonyms
pattern T' = Fix T
pattern F' = Fix F
pattern Not' t = Fix (Not t)
pattern And' l r = Fix (And l r)
pattern Or' l r = Fix (Or l r)
T' :: Exp
And' T' (Not' F') :: Exp
现在好的部分来了:用< code>fold
的一个定义来管理它们:
fold :: Functor f => (f a -> a) -> Fix f -> a
fold alg (Fix ffix) = alg $ fold alg <$> ffix
-- ffix :: f (Fix f)
-- fold alg :: Fix f -> a
-- fold alg <$> ffix :: f a
-- ^ Hey, remember when I said folds fold the subtrees first?
-- Here you can see it very literally
这是一个单态高度
height = fold $ \case -- LambdaCase extension: \case ... ~=> \fresh -> case fresh of ...
T -> 1
F -> 1
Not x -> x + 1
And x y -> max x y + 1
Or x y -> max x y + 1
现在是一个非常多态的<code>高度</code>(在你的例子中,它是1;哦,好的)。
height = fold $ option 0 (+1) . fmap getMax . foldMap (Option . Just . Max)
height $ Fix T -- 0
height $ Fix $ And (Fix T) (Fix $ Not $ Fix F) -- 2
参见递归方案包来学习这些黑魔法。它还使这一点适用于具有类型家族的基本类型,如< code>[],并消除了使用上述技巧< code >修复所有内容的需要。
我有下面的“height”函数,它返回树的高度。然而,当我尝试使用它时,我得到了这个异常。我怎样才能修好它?我还有一个函数“isBalancedTree”,它检查给定的树是否平衡。 *主要 ***异常:函数高度中的非穷尽模式
函数在Haskell中起主要作用,因为Haskell是一种函数式编程语言。与其他语言一样,Haskell确实具有自己的函数定义和声明。 函数声明由函数名称,其参数列表以及其输出组成。函数定义是实际定义函数的地方。让我们看看一个添加函数的示例,以详细了解此概念。 在这里,在第一行中声明了函数,在第二行中,我们编写了实际的函数,该函数将带有两个参数并产生一个整数类型的输出。 与大多数其他语言一样,Ha
问题内容: 我想使用Python的某些Haskell库(例如Darcs,Pandoc),但似乎在Python中没有直接的Haskell外部函数接口。有什么办法吗? 问题答案: 只要您可以获取Python代码来调用C,就可以调用已通过FFI导出的Haskell函数 另一种方法是编写标准IPC接口,在darcs和pandoc的情况下,仅将它们称为原始可执行文件,然后解析其输出可能是可行的方法。 至于在
(1) (2) (3)
在JavaScript中,该代码如下所示: 正如您所看到的,函数组合与JavaScript中的链接方法非常相似。我真的很喜欢链接方法从左到右读取的方式。在Haskell中,我可以使用中的函数和反向函数应用程序执行类似的操作,如下所示: 现在我想用点自由样式来写这个函数。使用函数组合,我将把它写如下: 函数组合的美妙之处在于它可以与自身组合,形成如上所示的“高阶函数组合”。因此,尽管它的类型签名直观
我现在在学习哈斯克尔。但我正在为“类型”而挣扎。 例如,函数的类型是