[Haskell] не могу разобраться с ошибкой (вывод типов)
От: eks314  
Дата: 09.08.08 19:49
Оценка:
Не могу понять почему в этом коде ambiguous type variable `a'


f :: Storable a => a -> (a, Int)
f x = (x, sizeOf (undefined :: a))


Обяъясните, пожалуйста.
Я считаю, что из контекста вызова f тип a должен быть выведен.
Re: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: VoidEx  
Дата: 09.08.08 22:25
Оценка: 1 (1) +1
Здравствуйте, eks314, Вы писали:

E>
E>f :: Storable a => a -> (a, Int)
E>f x = (x, sizeOf (undefined :: a)) 
E>


E>Обяъясните, пожалуйста.

E>Я считаю, что из контекста вызова f тип a должен быть выведен.

А чему же равен a?
Я в Хаскеле не силён, но почему бы не написать sizeOf x ?
Re: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: palm mute  
Дата: 09.08.08 22:28
Оценка:
Здравствуйте, eks314, Вы писали:

E>
E>f :: Storable a => a -> (a, Int)
E>f x = (x, sizeOf (undefined :: a)) 
E>


Вам нужны scoped type variables. Правильно будет так:
f :: forall a . Storable a => a -> (a, Int)
f x = (x, sizeOf (undefined :: a))
Re[2]: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: geniepro http://geniepro.livejournal.com/
Дата: 10.08.08 16:02
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Я в Хаскеле не силён, но почему бы не написать sizeOf x ?


Верно, так вполне даже работает:
f x = (x, sizeOf x)
Re[2]: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: eks314  
Дата: 13.08.08 15:07
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, eks314, Вы писали:


E>>
E>>f :: Storable a => a -> (a, Int)
E>>f x = (x, sizeOf (undefined :: a)) 
E>>


E>>Обяъясните, пожалуйста.

E>>Я считаю, что из контекста вызова f тип a должен быть выведен.

VE>А чему же равен a?

VE>Я в Хаскеле не силён, но почему бы не написать sizeOf x ?

Да, этот пример не самый подходящий. Я просто свел свой, немного более сложный код, к простому. В исходной задачи x — это возвращаемое значение функции.

Вот как это сейчас (без forall это не будет работать):

readFromFile :: forall a . Storable a => Handle -> IO a
readFromFile handle =
    alloca readPtrFromFile
    where 
        readPtrFromFile ptr = 
            let 
                bytesCount = sizeOf ( undefined :: a )
            in do { 
                actualBytesRead <- hGetBuf handle ptr bytesCount;
                assert (actualBytesRead == bytesCount) (peek ptr)
            }
Re[2]: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: eks314  
Дата: 13.08.08 15:10
Оценка:
Здравствуйте, palm mute, Вы писали:

PM>Вам нужны scoped type variables. Правильно будет так:

PM>
PM>f :: forall a . Storable a => a -> (a, Int)
PM>f x = (x, sizeOf (undefined :: a)) 
PM>


спасибо, помогло.
хотя я не понял логики этой проблемы. вроде ведь тип можно вывести на основании параметров. кажется, что это какие-то проблемы синтаксиса языка, хотя я понимаю, что вряд ли там все так тривиально.
Re[3]: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: palm mute  
Дата: 13.08.08 16:17
Оценка:
Здравствуйте, eks314, Вы писали:

Правильно будет так:
PM>>
PM>>f :: forall a . Storable a => a -> (a, Int)
PM>>f x = (x, sizeOf (undefined :: a)) 
PM>>


E>спасибо, помогло.

E>хотя я не понял логики этой проблемы. вроде ведь тип можно вывести на основании параметров. кажется, что это какие-то проблемы синтаксиса языка, хотя я понимаю, что вряд ли там все так тривиально.

Вы предположили, что вхождения "a" в строчках (1) и (2) должны обозначать одну и ту же переменную, но на самом деле для переменных типов таких правил видимости нет.

f :: Storable a => a -> (a, Int)   -- (1)
f x = (x, sizeOf (undefined :: a)) -- (2)


GHC в вашем коде видит следующее:
f :: forall a1 . Storable a1 => a1 -> (a1, Int)   -- (1)
f x = (x, sizeOf (undefined :: forall a2 . a2))   -- (2)


Никакой новой информации аннотация в строчке (2) компилятору не сообщила — он и так знал, что undefined имеет такой универсальный тип. Унифицировать переменные a1 и a2 причин нет — т.к. нет контекста, где бы выражение с типом a1 использовалось бы в качестве a2.

Расширение scoped type variables вводит области видимости для переменных типов, если они явно помечены ключевым словом forall.
Согласен, слово forall в GHC-Haskell перегружено и может сбивать с толку.
haskell types type_inference
Re[3]: [Haskell] не могу разобраться с ошибкой (вывод типов)
От: palm mute  
Дата: 13.08.08 17:09
Оценка:
Здравствуйте, eks314, Вы писали:


E>Да, этот пример не самый подходящий. Я просто свел свой, немного более сложный код, к простому. В исходной задачи x — это возвращаемое значение функции.

E>Вот как это сейчас (без forall это не будет работать):

В рамках Haskell 98 можно выкрутиться так:

derefPtr :: Ptr a -> a
derefPtr = undefined

readFromFile :: Storable a => Handle -> IO a
readFromFile handle =
    alloca readPtrFromFile
    where 
        readPtrFromFile ptr = 
            let 
                bytesCount = sizeOf (derefPtr ptr)
            in do { 
                actualBytesRead <- hGetBuf handle ptr bytesCount;
                assert (actualBytesRead == bytesCount) (peek ptr)
            }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.