2014-07-13 29 views
15

Trong khi lặp lại mã của tôi hướng tới một phiên bản đúng, tôi tình cờ gặp sự tò mò sau:Hãy-đổi tên phá vỡ chức năng mã

{-# LANGUAGE RankNTypes #-} 

module Foo where 

import Data.Vector.Generic.Mutable as M 
import Control.Monad.Primitive 

-- an in-place vector function with dimension 
data DimFun v m r = 
    DimFun Int (v (PrimState m) r -> m()) 

eval :: (PrimMonad m, MVector v r) => DimFun v m r -> v (PrimState m) r -> m() 
eval = error "" 

iterateFunc :: (PrimMonad m, MVector v r) 
      => (forall v' . (MVector v' r) => DimFun v' m r) -> DimFun v m r 
iterateFunc = error "" 

f :: (PrimMonad m, MVector v r) 
     => DimFun v m r 
f = error "" 

iteratedF :: (MVector v r, PrimMonad m) 
      => v (PrimState m) r -> m() 
iteratedF y = 
    let f' = f 
    in eval (iterateFunc f') y 

Mã này không biên dịch:

Testing/Foo.hs:87:14: 
    Could not deduce (MVector v0 r) arising from a use of ‘f’ 
    from the context (MVector v r, PrimMonad m) 
     bound by the type signature for 
       iteratedF :: (MVector v r, PrimMonad m) => 
           v (PrimState m) r -> m() 
     at Testing/Foo.hs:(84,14)-(85,39) 
    The type variable ‘v0’ is ambiguous 
    Relevant bindings include 
     f' :: DimFun v0 m r (bound at Testing/Foo.hs:87:9) 
     y :: v (PrimState m) r (bound at Testing/Foo.hs:86:11) 
     iteratedF :: v (PrimState m) r -> m() 
     (bound at Testing/Foo.hs:86:1) 
    In the expression: f 
    In an equation for ‘f'’: f' = f 
    In the expression: let f' = f in eval (iterateFunc f') y 

Testing/Foo.hs:88:26: 
    Couldn't match type ‘v0’ with ‘v'’ 
     because type variable ‘v'’ would escape its scope 
    This (rigid, skolem) type variable is bound by 
     a type expected by the context: MVector v' r => DimFun v' m r 
     at Testing/Foo.hs:88:14-27 
    Expected type: DimFun v' m r 
     Actual type: DimFun v0 m r 
    Relevant bindings include 
     f' :: DimFun v0 m r (bound at Testing/Foo.hs:87:9) 
    In the first argument of ‘iterateFunc’, namely ‘f'’ 
    In the first argument of ‘eval’, namely ‘(iterateFunc f')’ 
Failed, modules loaded: none. 

Tuy nhiên, nếu tôi thay đổi định nghĩa của iteratedF để

iteratedF y = eval (iterateFunc f) y 

mã biên dịch wtih GHC 7.8.2. Câu hỏi này không phải là về chữ ký hoặc kiểu dữ liệu lạ, điều này đơn giản là: tại sao đổi tên f thành f' ngắt mã? Điều này có vẻ như nó phải là một lỗi đối với tôi.

Trả lời

7

Vấn đề là tất nhiên không phải là đổi tên, nhưng các ràng buộc cho một biến mới. Vì iterateFunc là Hạng 2, nên cần có hàm đối số đa hình. Tất nhiên, f là đa hình trong v, vì vậy nó có thể được sử dụng. Nhưng khi bạn viết f' = f, nó không phải là rõ ràng những gì loại f' nên là: cùng loại đa hình như f, hoặc một số loại monomorphic, có thể tùy thuộc một số liên quan đến một loại biến trong iteratedF mà trình biên dịch đã không suy luận được nêu ra.

Trình biên dịch mặc định là tùy chọn đơn hình; như chi nói rằng đây là lỗi giới hạn đơn cấu hình ở đây nên nếu bạn tắt mã của mình thì thực sự biên dịch.

Tuy nhiên, cùng một vấn đề có thể xuất hiện ngay cả khi không có giới hạn đơn cấu hình trong mã RankNTypes, bạn không thể tránh hoàn toàn. Bản sửa lỗi đáng tin cậy duy nhất là chữ ký địa phương, thường cần phải có ScopedTypeVariables.

+2

Một trường hợp khác của hạn chế monomorphism sợ hãi, sau đó. – crockeea

+4

Tôi không nghĩ rằng việc đổi tên không thể tạo ra rắc rối trong Haskell thuần túy 98. Hãy xem xét 'let f = show in f 1 ++ f True'. –

12

Tắt giới hạn đa hình, tôi có thể biên dịch mã của bạn. Vì vậy, chỉ cần thêm

{-# LANGUAGE NoMonomorphismRestriction #-} 

ở đầu tệp của bạn.

Lý do cho các lỗi loại là định nghĩa

let f' = f 

không sử dụng một mô hình chức năng (ví dụ f' x y = ...), do đó hạn chế monomorphism đá trong và lực lượng f' là monomorphic, trong khi iterateFunc đòi hỏi một đa hình chức năng.

Ngoài ra, thêm một loại chú thích

let f' :: (PrimMonad m, MVector v r) => DimFun v m r 
    f' = f 
+1

Điều kỳ lạ là cờ 'NoMono ...' thậm chí còn cần thiết trong ghc-7.8 ... Tôi nghĩ rằng nó đã bị hạn chế độc lập hoàn toàn, nhưng dường như điều này chỉ hoạt động ở cấp cao nhất hoặc thứ gì đó. – leftaroundabout

+7

@leftaroundabout Tôi nghĩ rằng đó chỉ là GHCi – bennofs

Các vấn đề liên quan