2017-08-08 5 views
0

アソシエーションリスト(またはマップ)を使用して関数テーブルを構築したいとします。私はいくつかの簡単なテストを行い、以下を見つけました:完全にカルト化された関数は正常に機能しますが、部分的にカルト化された関数はアソシエーションリストに格納できません。ここでは正常に動作コードは次のとおりです。アソシエーションリスト(マップ)内の部分的にカリー化された関数

import Data.List 
import System.IO 

func1 :: IO() 
func1 = putStrLn "1" 

func2 :: IO() 
func2 = putStrLn "2" 

funcTable = [ (1, func1) 
      , (2, func2)] 

callFunc :: Int -> IO() 
callFunc i = do 
    let justFunc = lookup i funcTable 
    case justFunc of 
    Just func -> func 
    Nothing -> putStrLn "Wrong!" 

main = do 
    callFunc 1 
    callFunc 2 
    callFunc 3 

ただし、次のコードはコンパイルされません。

import Data.List 
import System.IO 

func1 :: IO() 
func1 = putStrLn "1" 

func2 :: String -> IO() 
func2 s = putStrLn s 

funcTable = [ (1, func1) 
      , (2, func2)] 

callFunc :: Int -> IO() 
callFunc i = do 
    let justFunc = lookup i funcTable 
    case justFunc of 
    Just func1 -> func1 
    Just func2 -> func2 "OK" 
    Nothing -> putStrLn "Wrong!" 

main = do 
    callFunc 1 
    callFunc 2 
    callFunc 3 

をコンパイルしないコードで私が作った唯一の変化は、私はfunc2のを変更したことです部分的にカレー化された機能。それを動作させるためのどんなトリックですか?

+4

「部分的にカレー化された」関数を「結合」リストに格納することはできません。問題は、2つの関数が同じ型でないことです。さらに、 'case'では' Just func1'は関数が本当に 'func1'であるかどうかをチェックしません。この場合、' func1'は*ローカル変数*です。 –

+0

'callFunc'関数がすべての関数について知っていなければならない場合、辞書を保持するポイントは何ですか? –

+1

'funcTable'の型を書きます。病気になっていることがわかります。 – chi

答えて

2

問題は機能に値を適用することとは関係ありません。問題は、両方の値が異なるタイプであることです。 [(1,func1),(2,func2)]のタイプは何ですか? [(Int,IO())][(Int, String -> IO())]?どちらも間違っています。

最も簡単な解決策は、異なるタイプの値を新しいタイプにラップすることです。

data Action 
    = SimpleAction (IO()) 
    | StringAction (String -> IO()) 

table :: [(Int, Action)] 
table = [(1, SimpleAction func1), (2, StringAction func2)] 

callFunc :: Int -> IO() 
callFunc i = case lookup i table of 
    Just (SimpleAction action) -> action 
    Just (StringAction action) -> action "OK" 
    Nothing -> error "wrong" 

なお、func1は機能ではありません。

関連する問題