为具有两个相同类型类的自定义数据类型实现应用函子

时间:2018-09-16 21:02:35

标签: haskell functor applicative

我试图使Twice成为应用程序的成员,但在functor实现中得到“'a'的冲突定义”:另外,我不确定如何正确实现<*>:// >

Traverse[Either[A, ?]]

3 个答案:

答案 0 :(得分:6)

我猜这些错误比语法上更具语法性。在您的定义中:

location.href = <endpoint>/authorize

Twice f f <*> Twice x x = Twice ((f x) (f x))定义相同:

Functor

您在开头写了两个fmap f (Twice a a) = Twice (f a) (f a)和两个f。 Haskell不允许这样做(Prolog允许,但是即使那样也可能不是您的意思)。

此外,您在正文中写道:

x

这意味着您将使用((f x) (f x))函数和f x参数进行函数调用,这又可能不是您想要的。

我们可以在语法上将其修复为:

f x

请注意,您仍然需要通过考虑为这些类型类记录的约束来证明这是有效的instance Functor Twice where fmap f (Twice a b) = Twice (f a) (f b) instance Applicative Twice where pure x = Twice x x Twice f g <*> Twice x y = Twice (f x) (g y)Functor实例。

答案 1 :(得分:2)

这里是问题及其纠正:

instance Functor Twice where
    -- fmap f (Twice a a) = Twice (f a) (f a)
    --               ^^^ you define `a` twice here. Replace this with:
    fmap f (Twice a b) = Twice (f a) (f b)

instance Applicative Twice where
    pure x = Twice x x -- You don't need brackets here so I removed them.
    -- Twice f f <*> Twice x x = Twice ((f x) (f x))
    -- ^^^^^^^^^     ^^^^^^^^^         ^^^^^^^^^^^^^
    -- You define f and x twice.
    -- You are also misusing brackets - this is not how to apply functions.
    -- A corrected version:
    Twice f1 f2 <*> Twice x1 x2 = Twice (f1 x1) (f2 x2)

首先,如果您不给单独的参数单独的名称,则此将会导致错误。想象我写f a a = a + 6,然后要求您评估f 1 2

第二,您误解了Haskell函数的应用方式。让我澄清一下:在大多数语言中,您写f(a,b,c),但是在Haskell中,您写f a b c。如果您写f (a b c),则读为f(a(b,c))

答案 2 :(得分:0)

混淆源于对数据和类型使用相同的名称;除新手Haskellers以外的所有人都可以接受的通用且推荐的做法。

现在,您可以使用其他名称,以减轻学习和习惯Haskell数据类型声明时的认知负担:

data Twice a = MkTwice a a deriving (Show)         -- 'Mk' is for "make"

-- Twice a                         -- a type
-- MkTwice :: a -> a -> Twice a    -- data constructor

instance Functor Twice where
    -- fmap (f :: a -> b) :: Twice a -> Twice b
    fmap f (MkTwice x y) = MkTwice (f x) (f y)     -- transform both fields

instance Applicative Twice where
    pure x = MkTwice x x                 -- create two fields from one value
    MkTwice f g <*> MkTwice x y = MkTwice (f x) (g y)  -- combine both fields

Twice a是类型,而a是类型变量。

MkTwice是此类型的数据构造函数。它从两个类型Twice a的值(例如ax :: a)中生成类型y :: a的值。值大约出现在Haskell定义中=的右侧。

它也用在模式中,用于类型Twice a的值。模式显示在Haskell定义中=的左侧。 Haskell的模式中不能有 no 个重复的模式变量。每个模式变量代表一些值。

每个类型变量代表一种类型。

我敢打赌,如果为类型和数据构造函数使用不同的名称,您不会犯这些错误。