gpt4 book ai didi

haskell - 为什么扩展我的函数依赖会消除非类型变量参数?

转载 作者:行者123 更新时间:2023-12-01 08:22:33 25 4
gpt4 key购买 nike

我一直在做一些工作来构建我自己的自定义前奏,我想构建一个 Callable 类型类来实现类型的函数应用程序 (($))除了功能。所以我使用多参数类型类构建了一个类型类:

{-# Language MultiParamTypeClasses #-}

import Prelude ()

class Callable a b c where
($) :: a -> b -> c

现在我继续将函数作为 Callable 类型类的实例,这需要我启用灵活的实例。

{-# Language MultiParamTypeClasses, FlexibleInstances #-}

import Prelude ()

id :: a -> a
id x = x

class Callable a b c where
($) :: a -> b -> c

instance Callable (a -> b) a b where
($) = id

这很好,现在我可以在函数上使用 ($) 了。因此,对我来说,下一个合乎逻辑的步骤是实现函数组合 ((.))。经过一番摆弄后,我意识到要做到这一点,我需要使 Callable 具有功能依赖性,因此我打开了功能依赖性。

{-# Language MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}

import Prelude ()

id :: a -> a
id x = x

class Callable a b c | a b -> c where
($) :: a -> b -> c

instance Callable (a -> b) a b where
($) = id

(.) :: (Callable f1 intype intermediate, Callable f2 intermediate outtype) => f2 -> f1 -> intype -> outtype
(.) a b c = a $ (b $ c)

这实际上编译得很好。事实上,如果我可以使用我的 (.) 来创建函数。但是,如果我尝试使用我的新函数(至少以我尝试过的任何方式),它无法进行类型检查并出现一个相当神秘的错误。

 ~/p/dynamo > ghci callable.hs
GHCi, version 8.4.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( callable.hs, interpreted )
Ok, one module loaded.
*Main> :t (id).(id)
(id).(id)
:: (Callable (a1 -> a1) c e, Callable (a2 -> a2) e d) => c -> d
*Main> ((id).(id)) $ ()

<interactive>:2:1: error:
• Non type-variable argument
in the constraint: Callable (c1 -> d) () c2
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall c1 d c2 a1 e a2.
(Callable (c1 -> d) () c2, Callable (a1 -> a1) c1 e,
Callable (a2 -> a2) e d) =>
c2
*Main>

我真的无法理解这个错误试图传达的意思。但它建议我打开灵活的上下文,所以我想我会试一试,如果它解决了很好的问题,如果它改变了错误,我可能会遇到问题。但是,如果我打开灵活上下文,错误并没有改变,事实上它甚至仍然提示我打开灵活上下文。

在这一点上,我想我会做一些阅读。我阅读了一些有关非类型变量参数 的问题,但我并不真的觉得我对我的特定问题有任何深入了解。正是在这一点上,我脑海中的某些东西让我想到也让 b 成为一个函数依赖。我不知道为什么,但这实际上解决了我的问题。这是工作代码的样子:

{-# Language MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}

import Prelude ()

id :: a -> a
id x = x

class Callable a b c | a -> b c where
($) :: a -> b -> c

instance Callable (a -> b) a b where
($) = id

(.) :: (Callable f1 intype intermediate, Callable f2 intermediate outtype) => f2 -> f1 -> intype -> outtype
(.) a b c = a $ (b $ c)

所以我的问题当然是为什么这行得通?我做错了什么?更改是如何解决的?

最佳答案

对于 fundep a b -> c,你说的是函数类型 (a) 和参数类型 (b)确定结果类型 (c)。将其更改为 a -> b c 意味着函数类型确定参数和结果类型,这正是您想要的:如果 a 替换为 a' -> b'ba'cb',那么确实函数类型包含消除歧义所需的信息。

关于haskell - 为什么扩展我的函数依赖会消除非类型变量参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50980399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com