2013-01-19 25 views
5

Tôi có một số lượng lớn các vị trí vector chức năng của các loạiphạm trù cho biến kiểu tạm thời

f :: (M.MVector v r, PrimMonad m) => 
    v (PrimState m) r -> v (PrimState m) r -> m() 

Những chức năng chủ yếu là làm việc tại chỗ, vì vậy nó là thuận tiện để có lập luận của họ là một vector có thể thay đổi để Tôi có thể soạn, lặp lại, v.v. Tuy nhiên, ở cấp cao nhất, tôi chỉ muốn làm việc với các vectơ thuần khiết "Haskell"/thuần túy.

Dưới đây là một ví dụ về các vấn đề:

{-# LANGUAGE TypeFamilies, 
      ScopedTypeVariables, 
      MultiParamTypeClasses, 
      FlexibleInstances #-} 

import Data.Vector.Generic as V hiding (eq) 
import Data.Vector.Generic.Mutable as M 
import Control.Monad.ST 
import Control.Monad.Primitive 

f :: (M.MVector v r, PrimMonad m) => 
    v (PrimState m) r -> v (PrimState m) r -> m() 
f vIn vOut = do val <- M.read vIn 0 
       M.write vOut 0 val 

applyFunc :: (M.MVector v r, PrimMonad m, V.Vector v' r, v ~ Mutable v') => 
      (v (PrimState m) r -> v (PrimState m) r -> m()) -> v' r -> v' r 
applyFunc g x = runST $ do 
        y <- V.thaw x 
        g y y -- LINE 1 
        V.unsafeFreeze y 

topLevelFun :: (V.Vector v r) => r -> v r 
topLevelFun a = 
    let x = V.replicate 10 a 
    in applyFunc f x -- LINE 2 

Các mã như kết quả bằng văn bản trong một lỗi trên dòng 1:

Could not deduce (m ~ ST s) 
    Expected type: ST s() 
    Actual type: m() 
    in the return type of g, LINE 1 

Bình luận ra dòng 1 kết quả trong các lỗi trên dòng 2:

Ambiguous type variable `m0' in the constraint: 
    (PrimMonad m0) arising from a use of `applyFun' 

Tôi đã thử nhiều cách đánh máy rõ ràng (sử dụng ScopedTypeVariables, foral rõ ràng ls, v.v.) nhưng không tìm được cách sửa chữa lỗi đầu tiên. Đối với lỗi LINE 1, có vẻ như m chỉ cần được suy ra là ST s vì tôi đang ở trong một runST.

Đối với Error Line 2 (với dòng 1 nhận xét ra), điều duy nhất tôi đã đi lên với công trình là

class Fake m v where 
    kindSig :: m a -> v b c 

instance Fake m v 

topLevelFun :: forall m v v' r . (V.Vector v' r, M.MVector v r, PrimMonad m, Fake m v, v ~ Mutable v') => r -> v' r 
topLevelFun a = 
    let x = V.replicate 10 a 
    in applyFunc (f::Transform m v r) x -- LINE 2 

mà rõ ràng là không đạt yêu cầu: Tôi có để tạo ra một lớp học giả, với một phương pháp vô nghĩa hơn nữa mà chỉ có công việc là chứng minh các loại đối số của lớp. Sau đó, tôi tạo một trường hợp chung cho tất cả mọi thứ để tôi có thể có m trong phạm vi trong topLevelFun, để tôi có thể thêm một ràng buộc và đúc f. Co cach tôt hơn ma.

Tôi có thể làm nhiều thứ sai ở đây, vì vậy mọi đề xuất sẽ hữu ích.

+0

'applyFunc' hứa sẽ hoạt động với bất kỳ' PrimMonad m' nào mà _caller_ chọn, nhưng sau đó 'runST $ do ...' buộc 'm' thành' ST s'. Bạn có thể sửa lỗi đó bằng cách nói rằng 'g' làm việc cho bất kỳ' PrimMonad m' _you_ nào, hoặc chỉ bằng cách giới hạn 'm' thành' ST s'. Đây là [code] (http://hpaste.org/80991). Nếu điều này thực sự trả lời vấn đề của bạn, hãy cho tôi biết và tôi sẽ viết ra một câu trả lời. – Vitus

+0

Tôi tin điều này hoạt động, với một số thay đổi nhỏ. Hãy chắc chắn để thêm 'Rank2Types' để nhập khẩu ngôn ngữ, và loại rank2 trong 'applyFunc' nên được (forall m. (PrimMonad m) => ...) Rất cám ơn! Rank2Types kéo qua cuối cùng. – crockeea

+0

Ah vâng, tôi đã quên 'RankNTypes' trong' .ghci'. Nhân tiện, tôi tin rằng 'Rank2Types' đang bị phản đối vì lợi ích của' RankNTypes'. – Vitus

Trả lời

1

Loại sau cho applyFunc có phù hợp với bạn không?

applyFunc :: (Vector v a) => 
    (forall s. Mutable v s a -> Mutable v s a -> ST s()) 
    -> v a -> v a 

Điều đó sẽ biên dịch với vấn đề ra quá lâu như bạn có phần mở rộng Rank2Types, mà bạn cần bởi vì bạn làm việc với một chức năng mà phải làm việc trên tất cả ST monads. Lý do cho việc này là loại runST(forall s. ST s a) -> a, do đó phần thân của mã sau runST cần hoạt động cho tất cả s, do đó cần g hoạt động cho tất cả s.

(Thay vào đó, bạn có thể thực hiện một chức năng hoạt động với tất cả PrimMonads nhưng có ít công cụ hơn).

GHC không thể suy ra loại xếp hạng cao hơn. Có nhiều lý do rất tốt để không suy RankNTypes (nó là undecidable), và mặc dù Rank2 là về mặt lý thuyết kết luận, người dân GHC quyết định cho sự cai trị "suy ra khi và chỉ khi các loại nguyên tắc là một loại Hindley-Milner" mà cho những người như tôi là rất dễ dàng để lý do về, và làm cho công việc nhà biên dịch biên dịch không quá khó.

Trong các nhận xét bạn hỏi về việc lấy một bộ dữ liệu.Bộ dữ liệu với các loại đa hình đòi hỏi ImpredicativeTypes và có thể được thực hiện như

applyFuncInt :: (Vector v a) => 
    ((forall s. Mutable v s a -> Mutable v s a -> ST s()),Int) 
    -> v a -> v a 
applyFuncInt (g,_) x = runST $ do 
          y <- V.thaw x 
          g y y 
          V.unsafeFreeze y 

mặc dù, thông thường nó sẽ tốt hơn nếu chỉ đơn giản là vượt qua số như một đối số riêng biệt.

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