我正在尝试为Tree编写仿函数(此类型的形式如下)
data Tree a = Empty | Node a (Tree a) (Tree a)
instance Functor Tree where
fmap f Empty = Empty
fmap f (Node a x y) = Node (f a) (fmap f x) (fmap f y)
它似乎有效,但更优雅(我是haskell的新手)解决方案呢?
第二个问题是讲师写了签名:fmap :: (a -> b) -> f a -> f b
对我来说,它是(a->b) -> Tree a -> Tree b
,但编译器ghci不接受它。重点在哪里?
答案 0 :(得分:1)
更优雅的解决方案呢?
完全没问题。所有其他未使用任何辅助函数的解决方案看起来或多或少都相同。我唯一要改变的是将=
和名称x
和y
对齐为l
和r
(指左右分支):
instance Functor Tree where
fmap _ Empty = Empty
fmap f (Node a l r) = Node (f a) (fmap f l) (fmap f r)
但是,这是我的个人意见。让我们来看看真正的问题,fmap
的类型:
第二个问题是讲师写了签名:
fmap :: (a -> b) -> f a -> f b
[...]
首先,讲师的签名有点错误。 fmap
的完整签名是
fmap :: Functor f => (a -> b) -> f a -> f b
约束Functor f
很重要。它限制了fmap
对Functor
实例的使用。现在这不是你遇到的问题:
对我来说,它是
(a->b) -> Tree a -> Tree b
,但编译器ghci不接受它。重点在哪里?
啊,您已尝试在fmap
实例中为Functor Tree
指定类型签名,对吗?
instance Functor Tree where
fmap :: (a -> b) -> Tree a -> Tree b
fmap = ...
嗯,这是不允许的。毕竟,fmap
的类型不是 (a -> b) -> Tree a -> Tree b
,而是上面更一般的类型。对于单个绑定使用两种类型的签名有点但不完全相似:
foo :: Eq a => a -> a -> Bool
foo :: () -> () -> Bool
这也是不允许的。请注意,如果您愿意,可以启用实例签名with an extension。如果您只想将其用于文档,则可以使用注释代替-XInstanceSigs
:
instance Functor Tree where
-- fmap :: (a -> b) -> Tree a -> Tree b
fmap = ...
TL; DR :fmap
的类型由class Functor
中的声明提供,它已由f
instance
中的sklearn.RandomForestClassifier(n_jobs=3,n_estimators=100,class_weight='balanced',max_features=None,oob_score=True)
指定1}}定义。
答案 1 :(得分:0)
您的解决方案非常优雅。另一种选择是使用fmap
定义traverse
:
import Data.Traversable
-- Preorder traversal based on the way you defined the Node constructor. Could use any traversal.
instance Traversable Tree where
traverse _ Empty = pure Empty
traverse f (Node v l r) = Node <$> f v <*> traverse f l <*> traverse f r
instance Functor Tree where
fmap = fmapDefault
instance Foldable Tree where
foldMap = foldMapDefault
我不会说这更优雅,但如果你想要所有这些情况,并且不想derive
他们这是一个简单的方法。