আধুনিক জিএইচসি সংস্করণগুলিতে কি কোনও ধরণের প্রুফ মুছা আছে?


22

ধরুন আমার কাছে একটি প্যারামিটার রয়েছে যা কেবলমাত্র টাইপ সিস্টেমের সুবিধার জন্যই বিদ্যমান, উদাহরণস্বরূপ এই ছোট প্রোগ্রামের মতো:

{-# LANGUAGE GADTs #-}
module Main where
import Data.Proxy
import Data.List

data MyPoly where
  MyConstr :: Proxy a -> a -> (Proxy a -> a -> Int -> Int) -> MyPoly

listOfPolys :: [MyPoly]
listOfPolys = [MyConstr Proxy 5 (const (+))
              , MyConstr Proxy 10 (const (+))
              , MyConstr Proxy 15 (const (+))]

main = print $ foldl' (\v (MyConstr p n a) -> a p n v) 0 listOfPolys

কাঠামোতে প্রক্সি আর্গুমেন্ট এবং সদস্যদের পলিমারফিক মাইপোলি বজায় রাখার সময় টাইপ চেকিংয়ে সহায়তা করার জন্য কেবল কম্পাইল সময়ে সত্যই উপস্থিত থাকা প্রয়োজন (এই ক্ষেত্রে, প্রোগ্রামটি এটি ছাড়াই সংকলন করবে, তবে এই স্বীকৃত উদাহরণটি আরও সাধারণ সমস্যা যেখানে রয়েছে প্রমাণ বা প্রক্সি যা কেবলমাত্র সংকলনের সময় প্রয়োজন) - প্রক্সিটির জন্য কেবলমাত্র একজন নির্মাতা রয়েছে, এবং প্রকারের আর্গুমেন্টটি ভুতের ধরণ om

Gc এর সাথে সংকলন -ddump-stgদেখায় যে কমপক্ষে এসটিজি পর্যায়ে, কনস্ট্রাক্টরের কাছে প্রক্সি যুক্তি বা কনস্ট্রাক্টরের তৃতীয় যুক্তির কোনও ক্ষয় হয় না।

এগুলিকে কেবল সংকলনকালীন হিসাবে চিহ্নিত করার কোনও উপায় আছে, বা অন্যথায় জিএইচসি কে প্রুফ মুছতে এবং সেগুলি বাদ দিতে সহায়তা করে?

উত্তর:


20

প্রকৃতপক্ষে, আপনার Proxyকোডগুলি কনস্ট্রাক্টরে সংরক্ষণের দিকে নিয়ে যায়:

ProxyOpt.listOfPolys8 :: ProxyOpt.MyPoly
[GblId, Caf=NoCafRefs, Unf=OtherCon []] =
    CCS_DONT_CARE ProxyOpt.MyConstr! [Data.Proxy.Proxy
                                      ProxyOpt.listOfPolys9
                                      ProxyOpt.listOfPolys4];

তবে, একটি ছোট পরিবর্তন সঙ্গে, আমরা চেয়েছিলেন অপ্টিমাইজেশন পেতে। আর নেই Proxy!

ProxyOpt.listOfPolys8 :: ProxyOpt.MyPoly
[GblId, Caf=NoCafRefs, Unf=OtherCon []] =
    CCS_DONT_CARE ProxyOpt.MyConstr! [ProxyOpt.listOfPolys9
                                      ProxyOpt.listOfPolys4];

আমি কি করেছিলাম? আমি Proxyমাঠটিকে কঠোর করে তুলেছি :

data MyPoly where
  MyConstr :: !(Proxy a) -> a -> (Proxy a -> a -> Int -> Int) -> MyPoly
           -- ^ --

সাধারণভাবে, আমরা বোতলগুলির কারণে অ-কঠোর প্রক্সিগুলি মুছতে পারি না। Proxyএবং undefinedউভয় প্রকারের Proxy aতবে তারা পর্যবেক্ষণের তুলনায় সমতুল্য নয়, তাই রানটাইমের সময় আমাদের তাদের আলাদা করতে হবে।

পরিবর্তে, একটি কঠোর Proxyশুধুমাত্র একটি মান থাকে, তাই GHC এটিকে অপ্টিমাইজ করতে পারে।

যদিও (অন-কনস্ট্রাক্টর) ফাংশন প্যারামিটারটি অপ্টিমাইজ করার অনুরূপ কোনও বৈশিষ্ট্য নেই। আপনার Field (Proxy a -> a -> Int -> Int)একটি প্রয়োজন হবে Proxyরানটাইম এ।


15

আপনি যা চান তা অর্জনের দুটি উপায় রয়েছে।

সামান্য পুরানো উপায় হ'ল জিএইচসি.প্রিম থেকে প্রক্সি # ব্যবহার করা , যা সংকলন-সময়ে মুছে ফেলার গ্যারান্টিযুক্ত।

{-# LANGUAGE GADTs, MagicHash #-}
module Main where

import Data.List
import GHC.Prim

data MyPoly where
  MyConstr :: Proxy# a -> a -> (Proxy# a -> a -> Int -> Int) -> MyPoly

listOfPolys :: [MyPoly]
listOfPolys = [MyConstr proxy# 5 (\_ -> (+))
              , MyConstr proxy# 10 (\_ -> (+))
              , MyConstr proxy# 15 (\_ -> (+))]

যদিও এটি কিছুটা জটিল।

অন্য উপায়টি Proxyপুরোপুরি ত্যাগ করা :

{-# LANGUAGE GADTs #-}

module Main where

import Data.List

data MyPoly where
  MyConstr :: a -> (a -> Int -> Int) -> MyPoly

listOfPolys :: [MyPoly]
listOfPolys = [ MyConstr 5  (+)
              , MyConstr 10 (+)
              , MyConstr 15 (+)
              ]

main = print $ foldl' (\v (MyConstr n a) -> a n v) 0 listOfPolys

আজকাল, আমাদের কাছে এমন কিছু সরঞ্জাম রয়েছে যা ছাড়াই কাজ করা সহজ করে তোলে Proxy: এক্সটেনশানগুলির মতো AllowAmbiguousTypesএবং TypeApplicationsউদাহরণস্বরূপ, আপনি যে ধরণের শব্দটি সরাসরি বলতে চান তা আপনি প্রয়োগ করতে পারেন। আপনার ব্যবহারের ক্ষেত্রে কী তা আমি জানি না, তবে এটি (স্বীকৃত) উদাহরণটি নিন:

import Data.Proxy

asTypeP :: a -> Proxy a -> a
asTypeP x _ = x

readShow :: (Read a, Show a) => Proxy a -> String -> String
readShow p x = show (read x `asTypeP` p)

>>> readShow (Proxy :: Proxy Int) "01"
"1"

আমরা পড়তে এবং তারপরে কিছু প্রকারের মান প্রদর্শন করতে চাই, সুতরাং প্রকৃত প্রকারটি কী তা বোঝানোর জন্য আমাদের একটি উপায় প্রয়োজন। আপনি এটি কীভাবে এক্সটেনশানগুলি সহ করবেন তা এখানে:

{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, ScopedTypeVariables #-}

readShow :: forall a. (Read a, Show a) => String -> String
readShow x = show (read x :: a)

>>> readShow @Int "01"
"1"

আমার মতে সর্বশেষ বিকল্পটি (কোনও প্রক্সি নেই) সেরা।
চি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.