Как именно работают синонимы типа? - PullRequest
7 голосов
/ 20 ноября 2010

Как получается, что следующий тип проверяет

{-# LANGUAGE RankNTypes #-}
module Main where

class Foo a where


type FunFoo = (Foo a) => a -> IO ()

data Bar = Bar {
  funFoo :: FunFoo
}

setFunFoo :: FunFoo -> Bar -> Bar
setFunFoo action bar = bar {funFoo = action}

, но при изменении подписи типа с setFunFoo на

setFunFoo :: ((Foo a) => a -> IO ()) -> Bar -> Bar

это не так?Есть ли способ выразить приведенный выше код без синонима типа FunFoo?

1 Ответ

7 голосов
/ 20 ноября 2010

Вам нужно добавить явное forall, например, так:

setFunFoo :: (forall a. (Foo a) => a -> IO ()) -> Bar -> Bar

Причина этого в том, что вы хотите, чтобы область действия переменной типа a была ограничена типом первого аргумента setFunFoo. Без явного forall тип desugared выглядит так:

setFunFoo :: forall a. ((Foo a) => a -> IO ()) -> Bar -> Bar
...