2016-04-06 9 views
0

GHC не разрешает/не распространяет ограничение в реализации по умолчанию некоторых моих членов класса. Поведение действительно странно, и мне кажется, что это ошибка.GHC не разрешает корректное ограничение в методах типов (ошибка/ограничение ghc?)

Может кто-нибудь помочь мне/объяснить мне, что случилось?

  1. Как я могу сказать GHC унифицировать a из декларации класса и a из метода класса, так что определение не является неоднозначным
  2. Есть ли что-то я не понимаю?

код:

module Foo where 
import Data.Proxy 

data Stuff a = Stuff 
    {content :: String} 

class HasStuff a where 
    stuff :: Stuff a 

    -- This works 
    useStuffOK :: Proxy a -> (Stuff a) 
    useStuffOK _ = (stuff) 

    -- those don't work, 
    -- (but I think ghc has all the information necessary to figure it out) 
    useStuffBAD :: Proxy a -> (Stuff a, String) 
    useStuffBAD _ = (stuff, content (stuff :: Stuff a)) 
    -- Could not deduce (HasStuff a1) arising from a use of ‘stuff’ 
    -- from the context (HasStuff a) 
    -- bound by the class declaration for ‘HasStuff’ 
    -- at Test.hs:(7,1)-(17,45) 

    useStuffBAD2 :: Proxy a -> String 
    useStuffBAD2 _ = content (stuff :: Stuff a) 
    -- Could not deduce (HasStuff a1) arising from a use of ‘stuff’ 
    -- from the context (HasStuff a) 
    -- bound by the class declaration for ‘HasStuff’ 
    -- at Test.hs:(7,1)-(17,45) 

instance HasStuff Int where 
    stuff = Stuff "ok" 

-- inference works here 
x :: Stuff Int 
x = stuff 

-- works here too 
x :: String 
x = content (stuff :: Stuff Int) 

Спасибо

+1

Это не ошибка. 'useStuffBAD _ = let x = stuff in (x, content x)' и 'useStuffBAD2 = content. useStuffOK'. Тип там действительно неоднозначен - вы можете ссылаться на любой «материал» в любом из этих выражений. 'useStuffOK' работает, потому что тип вывода задается сигнатурой типа. Поскольку 'content :: Stuff a -> String' не упоминает тип' a' в результате, использование этой функции неоднозначно, если тип явно не указан или не может быть выведен из контекста. – user2407038

+0

@ user2407038 только что отредактировал мой вопрос: когда я даю тип явно, он не работает ни потому, что ghc не унифицирует 'a' из объявления класса, а' a' из метода класса. В моем случае useStuffBAD явно указывает, какой экземпляр он должен выбрать. У меня все еще создается впечатление, что это проблема в ghc. – Rvion

+3

Я думаю, вам, возможно, понадобится '{- # LANGUAGE ScopedTypeVariables # -}' поверх вашего файла для работы - сам по себе ghc не знает, что 'Stuff a' from' (Stuff a, String) 'тот же как 'stuff :: Stuff a' – epsilonhalbe

ответ

0

в @epsilonhalbe и @ user2407038 указал, что я пропускал расширение ScopedTypeVariables