你能部分约束Haskell中的类型吗?

Ben*_*Ben 4 haskell type-inference

是否可以为包含"空白"的Haskell值提供类型签名以填充类型推断算法?

背景的极为人为的例子:

m = return ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is") 

b = isJust m
Run Code Online (Sandbox Code Playgroud)

这有效.使用isJust mb约束的类型mMaybe <something>,和m的定义约束的类型m<something> (Char, ((String, String), String, [String], String), String),并且编译器放在一起的那些信息两块制定出的精确类型m.

但是说我没有应用任何Maybe特定的功能m,所以我需要一个手动类型签名来阻止return多态.我不能这样说:

m :: Maybe a
m = return ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is")
Run Code Online (Sandbox Code Playgroud)

因为那是不对的.该类型是不是Maybe a所有的a,它是Maybe a对一些a我想编译器来推断; 有在节目足够的信息让编译器做到这一点,我们可以从我的第一个例子中看到的编译器能够放在一起多约束的类型,其中单独没有任何约束足以弄清楚什么类型的,但他们一起完全指定了类型.

我想要的是能够给出类型m :: Maybe _,其中_"你弄清楚这里有什么"的意思,而不是像"这是一个刚性的变量" m :: Maybe a.

有什么方法可以这样说吗?我能看到的替代方案是明确给出完整类型:

m :: Maybe (Char, ((String, String), String, [String], String), String)
m = return ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is")
Run Code Online (Sandbox Code Playgroud)

或者给表达式的一部分赋予类型签名,该部分签名具有约束Maybe类型签名部分的效果,但不a包括:

m = (return :: a -> Maybe a) ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is")
Run Code Online (Sandbox Code Playgroud)

或者在m没有明确类型签名的情况下离开并引入未使用的额外定义来约束m:

m = return ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is") 

b = isJust m
Run Code Online (Sandbox Code Playgroud)

或直接使用单态函数:

m = Just ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is")
Run Code Online (Sandbox Code Playgroud)

显然,这不是特定的Maybe,也不是* -> *类型构造函数的参数; 我能想象想要说"这个值是一个单子Int,对一些单子"没有希望地说"这个值是一个一元Int任何单子",或"这是从功能Int到一些其他类型的"不说"这是一个从功能Int任何其他type`.

我最感兴趣的是,为了可读性目的,是否允许我公平地直接声明上述关于值的声明,而不是难以阅读的解决方法(比如给出明确的类型签名return).我知道如果我的目标是简单地将额外的输入信息输入编译器以关闭模糊类型变量,那么有无数种方法可以做到这一点.

sha*_*haf 6

不幸的是,GHC并没有让你直接指定部分签名,尽管这样做会很棒.

在这种情况下m = return ... `asTypeOf` (undefined :: Maybe a),你想做的事情的一种方法是,asTypeOfPrelude函数在哪里:: a -> a -> a返回它的第一个参数但强制它与第二个参数统一.


这是你在评论中提出的一个好点 - undefined :: SomeType让我感到难过.这是另一个解决方案:

import Data.Proxy

proxiedAs :: a -> Proxy a -> a
proxiedAs = const
Run Code Online (Sandbox Code Playgroud)

现在你可以说m = return ... `proxiedAs` (Proxy :: Proxy (Maybe a)),而且看不到任何人.


Mic*_*man 5

你可以这样写:

asMaybe :: Maybe a -> Maybe a
asMaybe = id

m = asMaybe $ return ('I', (("don't", "really"), "care", ["what", "this"], "type"), "is")
Run Code Online (Sandbox Code Playgroud)

我用这种伎俩中的优雅,前奏,提供asByteString,asSet,asList,等.