在我看来,使用haskell非常好用的大部分内容都是(.)
,flip
,$
<*>
等组合器。感觉就像我能在需要时创建新语法。
前段时间我正在做一些事情,如果我可以“翻转”,那将是非常方便的。一个类型构造函数。假设我有一些类型构造函数:
m :: * -> * -> *
并且我有一个类MyClass
,它需要一个带有类型* -> *
的类型构造函数的类型。当然,我会选择以这样的方式对类型进行编码:
instance MyClass (m a)
但是假设我无法更改该代码,并假设真正符合MyClass
的内容就像是
type w b = m b a
instance MyClass w where
...
然后我必须激活XTypeSynonymInstances
。有没有办法创建一个&#34;类型级别的组合器&#34; Flip
我可以这样做:
instance MyClass (Flip m a) where
...
??或者我们在haskell中使用的常见运算符的其他类型级概括?这甚至是有用的还是我只是漫无目的?
编辑:
我可以这样做:
newtype Flip m a b = Flip (m b a)
newtype Dot m w a = Dot m (w a)
...
但是我必须使用数据构造函数Flip
,Dot
,...来进行模式匹配等等。值得吗?
答案 0 :(得分:11)
你的问题很有道理,但答案是:不,目前不可能。
问题在于(在GHC Haskell的类型系统中)你不能在类型级别拥有lambdas。对于你可能尝试的任何东西看起来它可以模拟或实现类型级别lambda的效果,你会发现它不起作用。 (我知道,因为我做了。)
你可以做的是声明你的翻转新类型,然后编写你想要的类的实例,痛苦地包装和解包(顺便说一句:使用记录语法),然后类的客户端可以使用类型签名中的新类型,不必担心细节。
我不是一个类型理论家,我不知道为什么我们不能拥有类型级别的lambdas的细节。我认为这与类型推断变得不可能有关,但我再也不知道了。
答案 1 :(得分:3)
您可以执行以下操作,但我认为它实际上并不十分有用,因为您仍然无法真正部分应用它:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
module Main where
class TFlip a where
type FlipT a
instance TFlip (f a b) where
type FlipT (f a b) = f b a
-- *Main> :t (undefined :: FlipT (Either String Int))
-- (undefined :: FlipT (Either String Int)) :: Either Int [Char]
答案 2 :(得分:2)
我在这里写答案只是为了澄清事情并讲述过去几年的成就。 Haskell 中有很多功能,现在您可以在类型中编写一些运算符。使用$
,你可以这样写:
foo :: Int -> Either String $ Maybe $ Maybe Int
避免使用括号而不是旧的
foo :: Int -> Either String (Maybe (Maybe Int))