Sri*_*aic 2 haskell ghc functional-dependencies
我一直在做一些构建我自己的自定义前奏的工作,我想构建一个Callable类型类,它将($)为函数以外的类型实现函数application().所以我使用多参数类型类构建了一个类型类:
{-# Language MultiParamTypeClasses #-}
import Prelude ()
class Callable a b c where
($) :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)
现在我继续将函数作为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
Run Code Online (Sandbox Code Playgroud)
这很好,现在我可以($)在函数上使用.因此,对我来说,下一个合乎逻辑的步骤是实现函数组合((.)).经过一段时间的努力,我意识到为了做到这一点,我需要在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)
Run Code Online (Sandbox Code Playgroud)
这实际上编译正常.事实上,如果我可以使用我的(.)功能.但是,如果我尝试使用我的新功能(至少以我尝试过的任何方式),它就不会出现相当神秘的错误.
~/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>
Run Code Online (Sandbox Code Playgroud)
我真的无法理解这个错误试图传达的内容.但它表明我打开灵活的上下文所以我认为我会给它一个旋转,如果它解决了这个问题很好,如果它改变了错误我可能会遇到问题.但是,如果我打开灵活的上下文,错误不会改变,事实上它甚至仍然暗示我打开灵活的上下文.
此时我以为我会做一些阅读.我读了几个问题Non type-variable argument,但我并不觉得我对我的特定问题有任何了解.正是在这一点上,我脑子里的某些东西让我想到了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)
Run Code Online (Sandbox Code Playgroud)
所以我的问题当然是为什么这样做有效?我做错了什么,改变是如何解决的?
使用fundep a b -> c,你会说函数type(a)和参数type(b)确定结果类型(c).更改此值a -> b c意味着函数类型确定参数和结果类型,这是您想要的:如果a替换为a' -> b',bwith a'和cwith b',那么函数类型确实包含消除歧义所需的信息.
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |