2011-12-01 25 views
17

Dưới đây là một số pragmas và một số hàng nhập khẩu:Loại lỗi với cấp bậc-2 chủng loại và chức năng thành phần

{-# LANGUAGE ScopedTypeVariables #-} 

import Control.Monad.ST 
import Data.Array.ST 
import Data.Array 

Bây giờ đây là vấn đề của tôi. Các typechecks mã sau:

foo :: forall a. a -> [a] 
foo x = elems $ runSTArray $ do 
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a) 

Tuy nhiên, khi tôi thay thế $ với thành phần:

foo :: forall a. a -> [a] 
foo x = elems . runSTArray $ do 
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a) 

tôi nhận được lỗi này:

Couldn't match expected type `forall s. ST s (STArray s i0 e0)' 
      with actual type `ST s0 (STArray s0 Int a)' 
In the expression: 
    newListArray (1, 10) (replicate 10 x) :: ST s (STArray s Int a) 
In the second argument of `($)', namely 
    `do { newListArray (1, 10) (replicate 10 x) :: 
      ST s (STArray s Int a) }' 
In the expression: 
     elems . runSTArray 
    $ do { newListArray (1, 10) (replicate 10 x) :: 
      ST s (STArray s Int a) } 

gì werid là, nếu tôi cung cấp cho các chức năng tạo thành tên riêng, sau đó gõ lại lần nữa:

elemSTArray = elems . runSTArray 

foo :: forall a. a -> [a] 
foo x = elemSTArray $ do 
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a) 

Tôi không chắc những gì đang xảy ra ở đây. Tôi mong đợi đoạn mã thứ hai để đánh máy độc đáo. Và tôi không hiểu tại sao nó lại gõ lại nếu tôi cung cấp cho hàm được tạo ra theo tên riêng của nó.

Đây là phiên bản đơn giản của một số mã mà tôi đã phá vỡ khi nâng cấp từ GHC 6.2 lên 7 và tôi đang cố gắng hiểu tại sao điều này xảy ra ngay bây giờ. Cảm ơn bạn đã trợ giúp!

+0

Tôi không thực sự là một lập trình viên Haskell, nhưng ưu tiên của thành phần liên quan đến '$' là gì? Điều gì xảy ra nếu bạn ngoặc đơn biểu thức con 'elems. runSTArray'? – Gian

+1

Tôi không thể sao chép điều này bằng GHC 6.12.1. – opqdonut

+0

Gian: '$' có mức ưu tiên thấp hơn '.', vì vậy nếu tôi ngoặc đơn biểu thức con, nó sẽ hoạt động giống nhau. opqdonut: Điều này đã không xảy ra với tôi trên GHC 6.2 nhưng nó có trên GHC 7.0.3 – Drekembe

Trả lời

15

Như bạn đã gợi ý ở trong tiêu đề của bài viết của bạn, vấn đề đã làm với runSTArray có một kiểu đa hình của bậc 2.

runSTArray :: Ix i => (forall s. ST s (STArray s i e)) -> Array i e 

Với

elems :: Ix i => Array i e -> [e] 

($) :: (a -> b) -> a -> b 

viết runSTArray $ ... có nghĩa là biến loại a trong lược đồ kiểu của ($) cần được khởi tạo với một loại đa hình hơn là một loại đơn hình. Điều này đòi hỏi cái gọi là đa hình không thể đoán trước. Cách GHC thực hiện đa hình mang tính giải thích được giải thích trong bài báo ICFP 2008 của Dimitrios Vytiniotis, Stephanie Weirich và Simon Peyton Jones: FPH : First-class Polymorphism for Haskell. Điểm mấu chốt là trong khi FPH thường cung cấp cho bạn hành vi mà bạn mong đợi, thì khả năng gõ đôi khi không được bảo quản dưới các phép biến đổi đơn giản như các biến bạn mô tả trong câu hỏi của bạn: xem Phần 6.2 của bài báo nói trên.

9

Stefan đánh bại tôi vào câu trả lời - bit khó khăn là nó không phải là $ vs . giữa elemsrunSTArray đó là vấn đề - đó là $ sau runSTArray. Kể từ khi something $ rankNthing là rất phổ biến, có một chút thông minh (tôi quên các chi tiết) mà cố gắng để cho bạn làm điều đó như là một trường hợp góc. Nhưng bằng cách nào đó bằng cách sử dụng bố cục trước đó để ngăn chặn điều này. Vị trí của vấn đề được chứng minh bằng thực tế là những điều sau đây sẽ đánh máy:

foo x = (elems . runSTArray) (
    (newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int String))) 

Tôi không chắc chắn đây là lỗi, nhưng chắc chắn là hành vi không mong muốn đáng để tạo vé, vì có thể vẫn là một thuật toán tốt hơn để nắm bắt các trường hợp như trường hợp bạn cung cấp.

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