2017-02-05 43 views
2

определение Bind класса в прелюдии является:переплета экземпляр класса для частично применяемых функций

class Apply m <= Bind m where 
    bind :: forall a b. m a -> (a -> m b) -> m b 

Это может быть прочитан как функция принимает два входных параметров, значение в монадическое контексте (m a) и функцию (a -> m b) и возврат значения в монадическом контексте (m b).

Экземпляр Bind для частично прикладной функции определяется следующим образом:

instance bindFn :: Bind ((->) r) where 
    bind m f x = f (m x) x 

который является функцией, принимая три параметров. Как это выглядит?

Если я пытаюсь заменить m a на более конкретного типа я получаю (поправьте меня, если я ошибаюсь):

(((->) ??) a) -> (a -> (((->) ??) b)) -> (((->) ??) b) 

что эквивалентно

(?? -> a) -> (a -> (?? -> b)) -> (?? -> b) 

Предполагая, что переменная m является оценка до (?? -> a), f будет привязан к a -> ?? -> b и x ко второму ??.

Является ли мое рассуждение правильным?

ответ

3

Чтобы добавить к тому, что swizard сказал (что правильно), один из способов проверить, что подпись типа функции класса типа, когда она была специализирована для конкретного экземпляра, - это записать ее и посмотреть, согласуется ли psci:

> :type bind :: forall r a b. (r -> a) -> (a -> r -> b) -> (r -> b) 
forall r a b. (r -> a) -> (a -> r -> b) -> r -> b 

Так что ваши рассуждения действительно правильные. Если бы мы выписали неправильный тип, мы бы дали ошибку типа:

> :type bind :: forall r. r -> r 
Error found: 
[...] 
    Could not match type [...] with [...] 
[...] 

Кроме того, только в случае, если вы не были уже осведомлены, тип функции конструктора -> является правоассоциативным, так a -> (r -> b) то же самое, что и a -> r -> b.

6

Which is a function taking three parameters. How does that typecheck?

Насколько я знаю, в текущем контексте этой функции подписи:

 
bind m f x = f (m x) x 

должен быть равен просто:

 
bind m f = \x -> f (m x) x