如何在这里避免显式类型签名?

Lan*_*dei 6 haskell typeclass

class Listy a b where
   fromList :: [b] -> a
   toList :: a -> [b]
   lifted :: ([b] -> [b]) -> (a -> a) 
   lifted f = fromList . f . toList

data MyString = MyString { getString :: String } deriving Show

instance Listy MyString Char where
  toList = getString
  fromList = MyString
Run Code Online (Sandbox Code Playgroud)

现在我需要写例如lifted (reverse::(String -> String)) (MyString "Foobar").是否有诀窍避免需要类型签名?

Mat*_*hid 11

本质上问题是设置类型a并不告诉编译器它是什么类型b.你可能会认为,既然只有一个类的实例(其中aMyStringbChar),但任何人都可以随时添加新的实例.因此,事实上,只有一个实例,现在并不能帮助编译器决定你想要什么类型.

对此的解决方案是使用功能依赖关系或类型系列.后者是较新的解决方案,旨在最终"替换"前者,但现在两者仍然得到完全支持.FD是否会消失还有待观察.无论如何,FDs:

class Listy a b | a -> b where ...
Run Code Online (Sandbox Code Playgroud)

基本上这说"每个人只能有一个类实例a".换句话说,一旦你知道a,你总能确定b.(但不是反过来.)班上的其他人看起来像以前一样.

替代方案是TF:

class Listy a where
  type Element a :: *
  ...

instance Listy MyString where
  type Element MyString = Char
  ...
Run Code Online (Sandbox Code Playgroud)

现在调用b它而不是被调用的第二种类型Element a.该单词的Element行为类似于一个类方法,它采用listy类型并返回相应的元素类型.然后你可以做

instance Listy ByteString where
  type Element ByteString = Word8
  ...

instance Listy [x] where
  type Element [x] = x
  ...

instance Ord x => Listy (Set x) where
  type Element (Set x) = x
  ...
Run Code Online (Sandbox Code Playgroud)

等等.(Listy对于上面的所有类型来说,这不一定有意义;这些只是如何定义类的示例.)


Yur*_*ras 5

您可以尝试-XFunctionalDependencies

class Listy a b | a -> b where
   fromList :: [b] -> a
   toList :: a -> [b]
   lifted :: ([b] -> [b]) -> (a -> a) 
   lifted f = fromList . f . toList
Run Code Online (Sandbox Code Playgroud)